[Super Mario 64 menu theme]
When we write
const x = 0.1
or in decimal is
const x = 0.1000000000000000055511151231257827021181583404541015625
For the same reason, when we write
const y = 0.2
And if we write
const z = 0.3
This means that when we write
const sum = 0.1 + 0.2
Again, we have lost a little precision, although for a different reason. At first, we lost some precision in the interpretation of the source code. Now, we have lost some more precision in the calculation.
Notice that this sum value, which we got by writing
Now, what happens when we try to log any of these values at the console?
So, if we try to log the value
we'll see the much shorter three-character string
at our console, because this is all that is necessary.
Note that yet again, we have lost some precision! That's three times now!
Strictly speaking, the only reason why
Similarly, if we try to log
out. And if we try to log
out. And finally, if we try to log the result of
0.1 + 0.2, which we remember is
we'll get [drum roll]...
So that's why
0.1 + 0.2 equals
0.30000000000000004, and does not equal
0.3. It's because we lost precision in three different places:
- when the code was interpreted,
- when the sum was calculated and
- when the result was output.
This all makes perfect sense now.
A double cannot represent every single possible real number. It can only represent approximately 264 distinct real numbers, all of them integer multiples of powers of 2. This includes, say, 0.125, but not 0.1. Instead we get the approximation behaviour seen above.
To explore further, you may find this package
precise-float which I made interesting:
> const preciseFloat = require('precise-float') undefined > preciseFloat.stringify(0.1) '0.1000000000000000055511151231257827021181583404541015625' > preciseFloat.stringify(0.2) '0.200000000000000011102230246251565404236316680908203125' > preciseFloat.stringify(0.3) '0.299999999999999988897769753748434595763683319091796875' > preciseFloat.stringify(0.1 + 0.2) '0.3000000000000000444089209850062616169452667236328125'