I\'m compiling and running the following program in 32 and 64 bit platforms:
int main()
{
double y = 8.34214e08;
double z = 1.25823e45;
return y * z == 8.
In general, never do equality checks with floating point numbers. You need to check whether the result you want differs from the result you get by less than a pre-set precision.
What is happening here is in all likelihood due to the multiplication being run on two different "platforms": once by your code, and once by the compiler, which may have a different precision. This happens with most compilers.
Your program would probably work if you compiled it with the same options that were used to compile the compiler (supposing the compiler was compiled by itself). But that would not mean you would get the correct result; you would be getting the same precision error the compiler is getting.
(Also, I'm assuming that the compiler performs a straight multiplication and the parsing code recognizing floats does not enter into the equation. This might well be wishful thinking on my part).
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
int main()
{
double y = 8.34214e08;
double z = 1.25823e45;
return printf("%s\n", y * z == 8.34214e08 * 1.25823e45 ? "Equal" : "NOT equal!");
}
Forcing -O0 to avoid the compiler from optimizing out the whole code (thanks @markgz!), we get
$ gcc -m32 -O0 -o float float.c && ./float NOT equal! $ gcc -m32 -frounding-math -O0 -o float float.c && ./float Equal
For the record, since you got there before me :-),
-frounding-math
Disable transformations and optimizations that assume default floating-point rounding behavior. This is round-to-zero for all floating point to integer conversions, and round-to-nearest for all other arithmetic truncations. This option should be specified for programs that change the FP rounding mode dynamically, or that may be executed with a non-default rounding mode. This option disables constant folding of floating-point expressions at compile time (which may be affected by rounding mode) and arithmetic transformations that are unsafe in the presence of sign-dependent rounding modes.
The default is -fno-rounding-math.