Floating point numbers in JS
Javascript
0.1 + 0.2
0.30000000000000004
Java
0.1 + 0.2
0.30000000000000004
IEEE 754
- Sign: 0 => positive, 1 => negative
- Exponent: number of digits left or right the floating point that should be shifted
- Mantissa: binary digits of the number. Whole numbers => 2x, decimals => 2-x (or 1/2x)
Additional information
- +Infinity: Sign 0; Exponent 2047; Mantissa 0
- -Infinity: Sign 1; Exponent 2047; Mantissa 0
- NaN: Sign 0/1; Exponent 2047; Mantissa !== 0
What happens ?
- 100 (binary) = 4. (1 x 22 + 0 x 21 + 0 x 20 = 4)
- In JS numbers, any digit that exceeds the 52 bits of the mantissa are assumed to be 0
- JS numbers are converted from decimal to binary
- 0.125 in decimal = 125/1000 = 1/8 = 1/23 = 0.001 in binary
- 0.1 in decimal = 1/10 = 1/2 * 5
- 0.2 in decimal = 1/20 = 1/2 * 2 * 5
- π€ The decimal values in our binary representation are defined using 2-x (or 1/2x)
- π± No way to cleanly find a exponent that our number goes into
- π Weβll continue to get back decimal/fraction results until we run out of bits
- πΎ When the conversion exhausts its bits, itβll store the result
- π€·β In this case it ends in 100 in binary or 4
How to avoid that?
- Stop using JavaScript π
- Scale up our result to an integer and scale back after
- Example: 0.1 * 10, 0.2 * 10 = 1.0 + 2.0 = 3.0/10 = 0.3
toPrecision()
and toFixed()
for display purposes only
```js
function foo(x, y) {
return x.toPrecision() + y.toPrecision()
}
> foo(0.1, 0.2)
"0.10.2"
```
Math libraries
- sinful.js
- math.js
- BigDecimal