This is a duplicate and I will close it as such, but here is an example of why this works for Float
but not for Double
.
Instead of looking at Double
and Float
, let's look at two new types. Eighths
and Sixteenths
. Eighths
has 3 bits to represent fractional numbers, so you can represent 0
, 0.125
, 0.25
, 0.375
, 0.5
, 0.625
, 0.75
, and 0.875
. Sixteenths
has 4 bits to represent fractional numbers, so you can represent 0
, 0.0625
, 0.125
, 0.1875
, 0.25
, and so on. In both number types, it will be necessary to approximate floating point values by choosing the closest value to the one you wish to represent.
So lets look at what 1.1 + 0.1
looks like in Eighths
and Sixteenths
.
Eighths
1.1 = 1.125
0.1 = 0.125
1.2 = 1.25
1.1 + 0.1 = 1.125 + 0.125 = 1.25
so 1.1 + 0.1 == 1.2
in Eighths
Sixteenths
1.1 = 1.125
0.1 = 0.125
1.2 = 1.1875
1.1 + 0.1 = 1.125 + 0.125 = 1.25
so 1.1 + 0.1 != 1.2
in Sixteenths
.
The greater precision of Sixteenths
makes it possible to more accurately represent 1.2
with a smaller value when represented in Sixteenths
.
This is what is happening with Float
s and Double
s. There are more bits available to represent the numbers, but they are still approximations. When you do math with those approximations, the error combines in unexpected ways which is why it is ill advised to be using equals comparisons with floating point values.