Why is this true? Java appears to produce a result with a small discrepancy when multiplying two floats compared to C and even the Java Math.pow method.
Java:
float a = 0.88276923;
double b = a * a; // b becomes 0.779281497001648 <---- what???
b = Math.pow(a,2); // b becomes 0.7792815081874238
C:
float a = 0.88276923;
double b = a * a; // b becomes 0.7792815081874238
pow(a,2); // b becomes 0.7792815081874238
Update: Per Ed S.'s comment, I have also found that the C behavior changes depending on the compiler. Using gcc it appears to match the Java behavior. Using visual studio (depending on your target platform) it can produce the results seen above or those seen in Java. Ugh.
pow Example. The method raises a to the power of b and returns the result as double. In other words, a is multiplied by itself b times.
Float and doubleDouble is more precise than float and can store 64 bits, double of the number of bits float can store. Double is more precise and for storing large numbers, we prefer double over float.
As pst and trutheality have already wisely noted, C is promoting the float
to a double
before the multiplication. Actually, they are promoted to an 80-bit extended precision value when they are pushed onto the stack. Here is the assembler output (VS2005 x86 C89)
double b = a * a;
00411397 fld dword ptr [a]
0041139A fmul dword ptr [a]
0041139D fstp qword ptr [b]
The FLD Instruction
The FLD instruction loads a 32 bit, 64 bit, or 80 bit floating point value onto the stack. This instruction converts 32 and 64 bit operands to an 80 bit extended precision value before pushing the value onto the floating point stack.
Interestingly, if I build to target x64, the movss
instruction is used and you get a value of 0.779281497001648
as the result, i.e., what you are seeing in your java example. Give it a try.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With