Dev.to WebDev 🛠 Dev 👁 0 📖 1 min read

Split a bill three ways without losing a cent

Split a $103.25 bill three ways and the obvious code gives you a total that is a cent off. Here is the bug and a fix that is a few lines long. I ran every snippet in Node 22. The bug const each = Number((1

Split a $103.25 bill three ways and the obvious code gives you a total that is a cent off. Here is the bug and a fix that is a few lines long. I ran every snippet in Node 22.

The bug

const each = Number((103.25 / 3).toFixed(2)); // 34.42
console.log((each * 3).toFixed(2));            // "103.26"

103.25 / 3 is 34.41666..., which rounds to 34.42. Three of those is $103.26, one cent more than the bill. Round the other way and you are a cent short on other amounts. Either way, the parts do not add up to the whole.

The fix: split whole cents, then hand out the remainder

Work in integer cents. Give everyone the same base amount, then give one extra cent to the first few people until the remainder is used up.

function split(totalCents, n) {
  const base = Math.floor(totalCents / n);
  const rem = totalCents % n;
  return Array.from({ length: n }, (_, i) => base + (i < rem ? 1 : 0));
}

split(10325, 3);  // [3442, 3442, 3441]  sums to 10325
split(10000, 3);  // [3334, 3333, 3333]  sums to 10000
split(1, 3);      // [1, 0, 0]           sums to 1

Every result sums to the input, by construction. Nobody pays more than one cent different from anyone else.

Why not just toFixed?

toFixed rounds a binary floating-point number, so it can surprise you on values that look simple:

0.1 + 0.2        // 0.30000000000000004
(1.005).toFixed(2) // "1.00"

Both lines are real output from my run. Keeping money as integer cents sidesteps this: 87.50 at 18% is Math.round(8750 * 18 / 100), which gives 1575 cents, or $15.75.

Tests worth writing

  • A total that does not divide evenly (10325 by 3).
  • A total that does (10000 by 4).
  • Fewer cents than people (1 by 3).
  • One person (the split should return the whole amount).
  • Check that the parts always sum to the total, for a few hundred random totals and people counts.

Decide up front who gets the extra cent. First in the list is fine, but write it down so it does not change between screens.

How do you handle the leftover cent in your own code?

📰 Read the original article on Dev.to WebDev

Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.