|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Senior Member
Iscritto dal: Jan 2003
Città: Lucca
Messaggi: 2165
|
[C,C++] Problema con i float
Salve a tutti...
Ho uno strano problema riguardante la memorizzazione di un numero in una variabile float. Uso gcc/g++ e sono sotto debian. Provate a compilare questo test: Codice:
// g++ test.c -O3 -o test
// gcc test.c -O3 -o test
#include <stdio.h>
int main ( ) {
float myfloat;
myfloat = 10.0 / 7.2123;
printf ( "mem -> \t%1.20f\n", myfloat );
printf ( "fresh -> \t%1.20f\n", 10.0 / 7.2123 );
return 0;
}
Codice:
./test mem -> 1.38652026653289794922 fresh -> 1.38652025012825319550
__________________
Intel G1820T | Asus H87-Pro | 8Gb DDR3 1333Mhz | Crucial M4 64Gb | WD Green 2Tb | Xonar Essence ST My pictures on 500px Ultima modifica di Jonny32 : 04-04-2006 alle 21:05. |
|
|
|
|
|
#2 |
|
Moderatore
Iscritto dal: Nov 2003
Messaggi: 16211
|
Anzitutto, con la virgola mobile non puoi riprodurre esattamente tutte le frazioni, per cui entrano in gioco comunque degli errori.
Per la cronaca, due numeri in virgola mobile si considerano uguali non quando hanno la stessa rappresentazione, ma quando la loro differenza è inferiore in valore assoluto a una tolleranza opportuna. Come seconda cosa, il primo output è un float, il secondo è un double. Infatti, le costanti numeriche con il puntino sono per default double, e non float: quindi, 10.0 / 7.2123 è un'espressione numerica di tipo double, di cui perdi alcune cifre di precisione quando la converti in float per assegnarla a myfloat.
__________________
Ubuntu è un'antica parola africana che significa "non so configurare Debian" Scienza e tecnica: Matematica - Fisica - Chimica - Informatica - Software scientifico - Consulti medici REGOLAMENTO DarthMaul = Asus FX505 Ryzen 7 3700U 8GB GeForce GTX 1650 Win10 + Ubuntu |
|
|
|
|
|
#3 | |
|
Senior Member
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
|
Quote:
Il problema è dovuto agli arrotondamenti nei calcoli floating point. Oltre agli arrotondamenti dovuti ai calcoli in sè, c'è pure da tenere presente gli errori/arrotondamenti causati dalla visualizzazione dei numeri con la printf, che per farti vedere il numero esegue a sua volta ... altri calcoli sui numeri. Un float (32 bit) ha una parte significativa (mantissa) di 24 bit che equivale a una precisione di circa 7~8 digit. Avresti un po' più di digit con il double (64 bit), che con una parte significativa di 53 bit ha una precisione di circa 15~16 digit. Avresti lo stesso problema con questo codice: Codice:
float a = 34.18f;
float b = 34.17f;
float c;
float d = 0.01f;
c = a-b;
printf ("%f\n", c);
printf ("%f\n", d);
if (c == d)
printf ("Uguali\n");
else
printf ("Diversi\n");
0.010002 0.010000 Diversi È un problema generale, dovuto alla rappresentazione dei numeri in floating point e non dipende dal compilatore o dal sistema operativo usato.
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%) |
|
|
|
|
|
|
#4 | |
|
Senior Member
Iscritto dal: Nov 2005
Città: Texas
Messaggi: 1722
|
Quote:
Nel caso tu abbia problemi numerici, e' opportuno verificare le operazioni da fare a priori, e cercare la forma piu' conveniente. Ovviamente questi errori sono ineliminabili, ma in molti casi li puoi tenere sotto controllo. Per esempio, in molti casi, semplicemente applicando la distributiva o cambiando l'ordine degli addendi, si puo' ridurre il problema... High Flying Sottovento
__________________
In God we trust; all others bring data |
|
|
|
|
|
|
#5 |
|
Senior Member
Iscritto dal: Jan 2003
Città: Lucca
Messaggi: 2165
|
Grazie a tutti dell'interessamento...
Nella storia delle approssimazioni c'ero già inciampato altre volte, quello che proprio non riuscivo a capire era come due operazioni apparentemente uguali dassero output diverso... Sembrava quasi che memorizzare o no il valore in memoria influisse in qualche modo... Invece era soltanto per il fatto che stavo operando con dei double invece che con dei float... Codice:
// g++ test.c -O3 -o test
// gcc test.c -O3 -o test
#include <stdio.h>
int main ( ) {
float myfloat;
myfloat = 10.0f / 7.2123f;
printf ( "mem -> \t%1.15f\n", myfloat );
printf ( "fresh -> \t%1.15f\n", 10.0f / 7.2123f );
printf ( "exact -> \t%1.15lf\n", 10.0 / 7.2123 );
return 0;
}
Grazie a tutti!!! P.S.: Cmq il problema posto da andbin mi sembra abbastanza grave, almeno per coloro che volessero effettuare calcoli di tipo scientifico... Ci sono modi per evitare questo problema?
__________________
Intel G1820T | Asus H87-Pro | 8Gb DDR3 1333Mhz | Crucial M4 64Gb | WD Green 2Tb | Xonar Essence ST My pictures on 500px |
|
|
|
|
|
#6 | |
|
Senior Member
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
|
Quote:
myfloat = 10.0f / 7.2123f; e printf ( "fresh -> \t%1.15f\n", 10.0f / 7.2123f ); danno sempre lo stesso identico valore perché sono espressioni formate da costanti e quindi calcolate e risolte a tempo di compilazione dal compilatore nello stesso identico modo!!!
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%) |
|
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 15:30.



















