Newsgroup: it.comp.lang.c++
Titolo: Sto impazzendo! Una funzione restituisce un valore sbagliato dopo la prima chiamata!

Sto cercando di creare un semplicissimo algoritmo...
dato un n numero, se n è pari n = n/2, se è dispari n = 3n+1 e così
via finche non si raggiunge uno, il programma deve calcolare il numero
di passi necessari.
Ad esempio 3 = 3 10 5 16 8 4 2 1 = 8 numeri per arrivare all'uno.
E questo nel mio programma funziona.
Peccato che il programma richieda una piccola feature aggiuntiva: dati
due numeri i e j, fare in modo che il programma restituisca il numero
massimo di numeri per n compreso tra i e j compresi.
Es. i = 1 j = 4
n = 1 numeri = 1
n = 2 numeri = 2
n = 3 numeri = 8
n = 4 numeri = 3
quindi il programma stamperà 8.
Ecco il codice del mio programmino:
#include <iostream>
using namespace std;
bool pari(int n);
int calcola(int n);
int calcolamax(int n, int m);
bool pari(int n) // giusto per rendere + leggibile il codice
{
 if (n % 2)
  return false;
 return true;
}
int calcola(int n)
{
 int i;
 while(1)
 {
  if (n==1)
  {
   i++;
   return i;
  }
  if(pari(n))
   n /= 2;
  else
   n = (3 * n) + 1;
  i++;
 }
}
int calcolamax(int n, int m)
{
 int max = 0, risultato = 0;
 for(int i = n; i <= m; i++, risultato = 0)
 {
  risultato = calcola(i);
  if (risultato > max)
   max = risultato;
 } 
 return max;
}
 
 
int main()
{
 int i, j;
 cout << "Inserisci 2 numeri maggiori di 0 e minori di 10.000\n";
 cin >> i >> j;
 cout << i << " " << j << " " << calcolamax(i, j);
 system("PAUSE");
 return 0;
}
-----------------
il problema è che calcolamax(int n, int m) restituisce non il numero
massimo di calcola(n) con  i<=n<=j,  ma la sommatoria di calcola(n)
con i<=n<=j
es calcolamax(2, 3) restituisce 10, perchè calcola(2) + calcola(3) =
10, mentre dovrebbe restituire 8.
calcolamax(2,4) = 13, mentre dovrebbe sempre essere 8.
riporto la funzione per comodità
int calcolamax(int n, int m)
{
 int max = 0, risultato = 0;
 for(int i = n; i <= m; i++, risultato = 0)
 {
  risultato = calcola(i);
  if (risultato > max)
   max = risultato;
 } 
 return max;
}
quel risultato = 0 nella 3a riga l'ho aggiunto dopo sperando che
potesse risolvere la situazione, ma non dovrebbe essere necessario.
Usando il debugger di devc++, si nota che (prendendo come esempio n =
2 e m = 3) per i = 2 calcola(i) restituisce 2, mentre calcola(3)
restituisce 10!!!
E' come se la funzione calcola(int n) "sporcasse", e tutte le chiamate
successive venissero modificate, falsate da questa. Infatti anche 
cout << i << " " << j << " " << calcola(i) << " " << calcola(j);
dà un output sbagliato. prima viene eseguito calcola(j) (il cout
funziona così) e poi calcola(i). Il primo numero è sbagliato ed il
secondo è esatto. Quindi l'errore sta in calcola(int n), che dipende
da una qualche variabile esterna alla funzione, modificata dalla
funzione stessa, in modo che falsi tutte le funzioni successive... ma
quale?? dov'è l'errore in calcola(n)?
---
Membro numero 85 del Luigino Fans Club.
Luigino sei tutti noi!
Anche se ti ho plonkato il tuo ricordo sarà per sempre!


Il problema in realtà è nella funzione calcola perchè non hai inizializzato
la variabile i, basta mettere int i=0 invece che int i.
Non ho fatto molte prove ma sembra funzionare.

   if (n==1)
 >...........................
Banalmente: non inizializzi la variabile i
che quindi puo' contenere qualunque cosa !
in ogni caso il ciclo while (1) e' superfluo:
int Collatz(int n)
{
    int loop=1;
    while(n>1)    // per evitare loop infiniti per n=0
   {
     if (n&1) n=3*n+1;  // n dispari
     else n>>=1;        // n pari
     loop++;
   }
   return loop;
}
forse andrebbe aggiunto un controllo per possibili
overflow interi.
ciao,
g.


Altra cosa: nessuno ti assicura che n<m io nel cout del main specificherei
che il primo numero deve essere maggiore del secondo e metterei un ciclo
while che si ripeta finchè i numeri immessi non soddisfino tale relazione.