Sikau

How computers work · Day 4 · about 35 min

Fractions and floating point

Why 0.1 + 0.2 ≠ 0.3, what a float's bits mean, and why money uses integers.

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;
}

The rest of this lesson

  • Scientific notation in base 2explain
  • Rounding errors add upexplain
  • Exact?predict
  • Float or integer?match
  • Floats and moneywrite code
  • Badge quizquiz
  • What you learnedrecap

Continue this lesson free — run real code in your browser

Continue with Google

See all 13 lessons of How computers work