In Java, I've run this method:
private static void floatAddition() {
float a = 0.1F, b = 0.2F, c = a+b;
System.out.println(a + " + " + b + " = " + c);
}
and the result is 0.3
for floatAddition. I'm now trying to get behind why it is adding to a round result, and not to something slightly off due to floating points.
I've manually transformed 0.1
and 0.2
into binary 32-Bit system with IEEE 754 standard, this is what I got:
0.1 (decimal) = 0 01111011 10011001100110011001101 (binary)
0.2 (decimal) = 0 01111100 10011001100110011001101 (binary)
I now add these two together. Since the exponents are different, I have to bring them both to the bigger one (2^-3) so I'm unnormalizing 0.1.
0.1 (decimal) = 0.11001100110011001100111 * 2-3 (binary) 0.2 (decimal) = 1.10011001100110011001101 * 2-3 (binary)
This is the manual addition result:
0.1 (decimal) + 0.2 (decimal) = 10.01100110011001100110100 * 2-3 (binary)
In IEEE 754 standard, this would be
0 01111101 00110011001100110011010
Now for checking whether or not I'm correct, I've used this IEEE 754 Converter: http://www.h-schmidt.net/FloatConverter/IEEE754.html
According to this site, my result should've been 0.30000001192092896.
Why is my floating point calculation more exact than it should be?
Best Answer
Lets look at some quick code:
The output of this code is:
That last line is the hexadecimal representation of the value that is being rendered as 0.3.
So, lets look what C does.
And this produces the output:
You will note that the representation of the float value is equivalent.
I am certain that the code is properly following the specification. You may be confused at the float to string conversion, but that is something to be done with various formatting or other libraries to display what you want.
But the underlying floating point representation is exactly what it should be.
As an aside, the difference between the C and the Java can be seen by switching to
printf
where one is expected to be a bit more precise with the values:prints out:
Note the
printf
in Java matches theprintf
in C.Digging into the JLS we find in section 5.1.11,
Digging through this, one gets to
sun.misc.FloatingDecimal
which when created withFloatingDecimal(float f)
which goes through a fair bit of calculations to try to figure out what to display. Java8 changes this a little bit to do the BinaryToAsciiConverter, but the idea is still the same.