0.1 + 0.2 = 0.30000000000000004
Try it in any language. It's not a JavaScript bug: in binary, 0.1 is a repeating fraction (like 1/3 in decimal), so it's stored *rounded*. JavaScript numbers are 64-bit floating point: a sign bit, 11 exponent bits and 52 fraction bits — scientific notation in base 2.
Living with floats
- Compare with a tolerance, not ===.
- Store money as integer cents (or use a decimal library).
- Look at the real bits with a DataView.
function nearlyEqual(a, b, epsilon = 1e-9) {
return Math.abs(a - b) < epsilon;
}
function toCents(text) {
const [whole, frac = ""] = text.split(".");
return Number(whole) * 100 + Number(frac.padEnd(2, "0").slice(0, 2));
}
function addMoney(a, b) {
const cents = toCents(a) + toCents(b);
return Math.floor(cents / 100) + "." + String(cents % 100).padStart(2, "0");
}
function floatBits(x) {
const view = new DataView(new ArrayBuffer(8));
view.setFloat64(0, x);
let bits = "";
for (let i = 0; i < 8; i++) bits += view.getUint8(i).toString(2).padStart(8, "0");
return bits;
}