# Floating point calculation being too exact

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?

• Are you sure those are the correct values? What happens when you do this in say... C?
– user40980
Feb 20, 2016 at 14:32
• I don't know about Java, but C# allows using higher precision. In practice that means that 80 bit extended floating point values are used for calculations (using the x87 instruction set), which can then be reduced to 64 bit `double`s or 32 bit `float`s when necessary or convenient. This can result in performance benefits, but it also makes reasoning about the code very hard. Feb 20, 2016 at 14:38
• My guess is that the float->string conversion (for the printing) is being "helpful" by rounding the value to what most people expect. Feb 20, 2016 at 14:41
• This is my java snippet in an online IDE: tutorialspoint.com/… I have no clue of C, but this is what I got: tutorialspoint.com/… Feb 20, 2016 at 14:43
• @BartvanIngenSchenau Do you know a way to disable the "being friendly" feature? Feb 20, 2016 at 14:44

Lets look at some quick code:

``````public class Floats {
public static void main(String[] args) {
float a = 0.1F;
float b = 0.2F;
float c = a+b;
System.out.println(a + " + " + b + " = " + c);

System.out.printf("0x%8x", Float.floatToIntBits(c));
}
}
``````

The output of this code is:

``````0.1 + 0.2 = 0.3
0x3e99999a
``````

That last line is the hexadecimal representation of the value that is being rendered as 0.3.

So, lets look what C does.

``````#include <stdio.h>
int main (int argc, char* argv[]) {
float a = 0.1F;
float b = 0.2F;
float c = a + b;
printf("%f + %f = %f\n", a, b, c);
printf("0x%8x\n", *(unsigned int*)&c);
}
``````

And this produces the output:

``````0.100000 + 0.200000 = 0.300000
0x3e99999a
``````

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:

``````public class Floats {
public static void main(String[] args) {
float a = 0.1F;
float b = 0.2F;
float c = a+b;
System.out.println(a + " + " + b + " = " + c);
System.out.printf("%f + %f = %f\n", a, b, c);

System.out.printf("0x%8x", Float.floatToIntBits(c));
}
}
``````

prints out:

``````0.1 + 0.2 = 0.3
0.100000 + 0.200000 = 0.300000
0x3e99999a
``````

Note the `printf` in Java matches the `printf` in C.

Digging into the JLS we find in section 5.1.11,

If T is `float`, then use `new Float(x)`.

Digging through this, one gets to `sun.misc.FloatingDecimal` which when created with `FloatingDecimal(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.

• So my manual calculation is appearantly correct. Using e.g. System.out.format("%.20f%n", a+b); gives out my result. Thanks. Feb 20, 2016 at 14:53
• @Baustein there's a fair amount of code in the Float to string converter that is actually an interesting read to figure out how it works.
– user40980
Feb 20, 2016 at 14:57
• Nitpick: The C code violates strict aliasing. It would be better to use `memcpy` to copy the bytes of the `float` into the bytes of an integer. And I'd prefer using `uint32_t` here. Feb 20, 2016 at 16:24

Probably because 0.3f = 0.30000001192092896.

0.3f is the single precision floating point number closest to the real number 0.3. The real number 0.3 cannot be represented exactly as a single precision floating point number (or as any binary floating point number), therefore 0.3f must be slightly different from the real number 0.3.

Single precision floating point has a 24 bit mantissa. For 0.3, the highest bit of the mantissa has a value of 0.25 = 2^-2, the lowest bit has a value of 2^-25, and you'd have to expect a rounding error up to

2^-26 = 0.000 000 014 901 161

Actually, 0.3f was rounded up by

0.000 000 011 920 928 96

which is entirely in the range that you would expect.