Newsgroup: it.comp.lang.c
Titolo: Incongruenza di valori

Salve a tutti,
mi è capitato un problema un po' strano (magari è perfettamente
normale...) con il seguente codice :
float b;
b = (float) -0.0000001 ;
if ( b < 0 ) printf( " b < 0 true \n " );
if ( b == -0.0000001 ) printf ( " b == -0.0000001 true \n ");
if ( b == -0.0 ) printf ( " b == -0.0 true \n ");
if ( b == 0.0 ) printf ( " b == 0.0 true \n ");
printf( " b = %f\n ",b);
Inutile dire che il compilatore non segnala nemmeno un warning e a
run-time il valore di b è considerato negativo ed è uguale a
-0.000000 ( assurdo ! ). Questa incongruenza però può generare degli
errori in un programma e quindi mi chiedevo come risolverla, qualcuno
di voi ha avuto esperienza in tal senso ?
Grazie.
CoF.



Ora ho provato ad aggiungere anche la linea :
if ( fabs( b ) == 0.0 ) printf (" fabs ( b ) == 0.0 true \n ");
ma neanche questa da esito positivo!
Attendo vostri suggerimenti !
CoF.

 >b = (float) -0.0000001 ;
Non è necessario effettuare un cast esplicito da double a float, tanto viene
fatto implicitamente dal compilatore stesso. In entrambi i casi se il valore
double non ha una controparte float ottieni un undefined behavior.
La precisione dei float, ammettendo il caso che tu utilizzi un tipo float
rappresentato con 4 byte e con precisione decimale pari a 6 cifre - penso
sia il tuo caso - ti porta al troncamento nella conversione da double a
float del valore decimale corrispondente alla settima cifra.
Inoltre è da aggiungere che nelle operazioni di confronto tra valori a
virgola mobile non sempre porta a risultati attendibile. Per farti un
esempio mi è capitato pià volte - quando provavo il compilatore - di avere i
seguenti risultati:
float a = 10.44;
if(a > 10.439) printf("vero");
else printf("false");
a = 10.44;
if(a == 10.44) printf("vero");
else printf("false");
a = 10.555533;
if(a < 10.5) printf("vero");
else printf("false");
Nel primo caso da vero, nel secondo falso, nel terzo vero.
Purtroppo è sempre buona norma evitare questi tipi di confronti perché, come
hai potuto tu stesso vedere, non sempre sono veritieri.
Ciao.

hai potuto tu stesso vedere, non sempre sono veritieri.
ti ringrazio per l'aiuto ... Non è che per caso conosci un metodo per
identificare il valore -0.0 e convertirlo in 0.0 ...
grazie comunque,
ciao,
CoF.

 normale...) con il seguente codice :
E' perfettamente normale. E' un errore dovuto alla precisione nel 
rappresentare numeri a virgola mobile.
Esiste una costante FLT_EPSILON (o DBL_EPSILON per i numeri a doppia 
precisione) definito come il minimo valore di x per il quale (x + 1.0) != 
1.0. Usando questa nei confronti correggi l'errore.
-- 
In silenzio anche un idiota sembra intelligente. Ma non c'è problema,
l'idiota vuol sempre dire la sua.

1.0. Usando questa nei confronti correggi l'errore.
Ti ringrazio per l'aiuto.
ciao,
CoF.

 identificare il valore -0.0 e convertirlo in 0.0 ...
Totalmente dipende dall'implementazione. Alcuni compilatori automaticamente
sostituiscono nelle espressioni aritmetiche al -0.0 il corrispondente valore
0.0. Altri non lo fanno e mantegono i due valori separati, ma comunque in
caso di confronto li considerano uguali. Proprio per questo nasce
l'inutilità di una trasformazione di questo tipo, non potendo rilevare
quando effettivamente una variabile contiene un valore -0.0 se non in fase
di debug.
Ciao.