In generale, mai do equality checks with floating point numbers. È necessario verificare se il risultato desiderato differisce dal risultato ottenuto meno di una precisione prestabilita.
Ciò che sta accadendo qui è con ogni probabilità a causa della moltiplicazione eseguita su due diverse "piattaforme": una volta dal codice e una dal compilatore, che può avere una precisione diversa. Questo succede con mostcompilers.
tuo programma sarebbe probabilmente lavoro se si è compilato con le stesse opzioni che sono stati utilizzati per compilare il compilatore (supponendo che il compilatore è stato compilato da solo). Ma questo non significa che otterresti il risultato corretto; si otterrebbe lo stesso errore di precisione che il compilatore sta ottenendo.
(Inoltre, sto supponendo che il compilatore esegue una moltiplicazione dritto e il codice di analisi riconoscere carri non entra nell'equazione. Questo potrebbe anche essere un pio desiderio da parte mia).
Testing
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib64/gcc/x86_64-suse-linux/4.8/lto-wrapper
Target: x86_64-suse-linux
Configured with: ../configure --prefix=/usr --infodir=/usr/share/info --mandir=/usr/share/man --libdir=/usr/lib64 --libexecdir=/usr/lib64 --enable-languages=c,c++,objc,fortran,obj-c++,java,ada --enable-checking=release --with-gxx-include-dir=/usr/include/c++/4.8 --enable-ssp --disable-libssp --disable-plugin --with-bugurl=http://bugs.opensuse.org/ --with-pkgversion='SUSE Linux' --disable-libgcj --disable-libmudflap --with-slibdir=/lib64 --with-system-zlib --enable-__cxa_atexit --enable-libstdcxx-allocator=new --disable-libstdcxx-pch --enable-version-specific-runtime-libs --enable-linker-build-id --enable-linux-futex --program-suffix=-4.8 --without-system-libunwind --with-arch-32=i586 --with-tune=generic --build=x86_64-suse-linux --host=x86_64-suse-linux
Thread model: posix
gcc version 4.8.3 20141208 [gcc-4_8-branch revision 218481] (SUSE Linux)
#include <stdio.h>
int main()
{
double y = 8.34214e08;
double z = 1.25823e45;
return printf("%s\n", y * z == 8.34214e08 * 1.25823e45 ? "Equal" : "NOT equal!");
}
Forzare -O0 per evitare al compilatore di ottimizzare l'intero codice (grazie @markgz!), Otteniamo
$ gcc -m32 -O0 -o galleggiante float.c & & ./float NON uguale! $ gcc -m32 -frounding-math -O0 -o galleggiare float.c & & ./float Pari
Per la cronaca, dal momento che hai lì davanti a me :-),
-frounding -math
Disabilitare le trasformazioni e le ottimizzazioni che presuppongono il comportamento di arrotondamento a virgola mobile predefinito. Questo è round-to-zero per tutte le conversioni in interi da in virgola mobile e da arrotondato al più vicino per tutte le troncature aritmetiche di . Questa opzione deve essere specificata per i programmi che modificano la modalità di arrotondamento FP in modo dinamico o che potrebbe essere eseguita con una modalità di arrotondamento non predefinita.Questa opzione disabilita il piegamento costante delle espressioni in virgola mobile al momento della compilazione (che può essere influenzato dalla modalità di arrotondamento) e le trasformazioni aritmetiche che non sono sicure in presenza di modalità di arrotondamento dipendenti dal segno.
L'impostazione predefinita è -fno-rounding-math.
@waj: Non ho inoltrato la domanda. È una bella domanda. –
@SteveSummit ok, scusami per questo, ho ottenuto il downvote allo stesso tempo in cui hai risposto e StackOverflow non mostra chi ha votato. Ad ogni modo, posso conviverci, ma ho davvero bisogno di sapere le ragioni, ecco perché sto inviando una domanda qui in primo luogo. – waj
@Giorgi: in quella domanda c'è una differenza perché la variabile è dichiarata come "float" ei valori letterali sono "double". Qui tutti i valori sono doppi. – waj