This post explains a quiz originally shared as a LinkedIn poll.
🔹 The Question
const prices = [10.5, 20.3, 15.8];
const total = prices.reduce((sum, price) => {
return sum + price;
});
console.log(total);
console.log(typeof total);
Hint: Check what reduce returns when you omit the initial value and the array has only numbers.
🔹 Solution
Correct Answer: B) 46.599999999999994 and number
The output is:
46.599999999999994number
🧠 How this works
JavaScript uses IEEE 754 double-precision floating-point format to represent all numbers. This format cannot precisely represent many decimal fractions, leading to rounding errors during arithmetic operations.
When you add 10.5 + 20.3 + 15.8, the intermediate results accumulate small precision errors:
-
10.5 + 20.3=30.799999999999997(not exactly30.8) -
30.799999999999997 + 15.8=46.599999999999994(not exactly46.6)
This isn't a bug in JavaScript—it's how binary floating-point arithmetic works in virtually all programming languages (Python, Java, C++, etc.). The issue is that decimals like 0.1, 0.2, 0.3 cannot be represented exactly in binary, just like 1/3 cannot be represented exactly in decimal (0.333...).
The type remains number because JavaScript doesn't distinguish between integers and floats—everything is a 64-bit floating-point number.
🔍 Line-by-line explanation
const prices = [10.5, 20.3, 15.8]— creates an array of three floating-point numbers-
prices.reduce((sum, price) => { return sum + price; })— reduces the array:-
First iteration:
sum = 10.5(first element, since no initial value),price = 20.3- Returns:
30.799999999999997(not30.8due to floating-point precision)
- Returns:
-
Second iteration:
sum = 30.799999999999997,price = 15.8- Returns:
46.599999999999994(accumulated error)
- Returns:
-
First iteration:
console.log(total)→46.599999999999994console.log(typeof total)→number
The misleading part: Developers expect 10.5 + 20.3 + 15.8 to equal exactly 46.6 because that's how decimal arithmetic works on paper. But computers use binary representation, and these particular decimals don't have exact binary representations.
🔹 Real-World Impact
Floating-point precision errors cause serious issues in:
- E-commerce: Shopping cart totals that don't match item sum, causing payment gateway rejections or customer complaints
- Financial calculations: Invoice totals, tax calculations, currency conversions showing unexpected pennies
- Analytics dashboards: Metrics that should sum to 100% showing 99.99999999999999% or 100.00000000001%
-
Testing: Assertions like
expect(total).toBe(46.6)failing intermittently -
Data validation: Price comparisons using
===failing when values should be equal
🔹 The Fix
Option 1: Round to fixed decimal places
const total = prices.reduce((sum, price) => sum + price, 0);
const rounded = Math.round(total * 100) / 100;
console.log(rounded); // 46.6
Option 2: Use a decimal library for precision-critical work
import Decimal from 'decimal.js';
const total = prices
.map(p => new Decimal(p))
.reduce((sum, price) => sum.plus(price));
console.log(total.toString()); // "46.6"
Option 3: Format for display
console.log(total.toFixed(2)); // "46.60" (string)
console.log(Number(total.toFixed(2))); // 46.6 (number, rounded)
🔹 Key Takeaways
- JavaScript uses IEEE 754 floating-point arithmetic, which cannot precisely represent many decimal fractions
- Accumulating floating-point operations compounds precision errors
- Never use
===to compare floating-point results; use a tolerance:Math.abs(a - b) < 0.0001 - For financial calculations, work with integers (cents) or use decimal libraries like
decimal.jsorbig.js - Always round or format floating-point numbers before displaying to users
- This behavior is consistent across all IEEE 754-compliant languages, not unique to JavaScript
Top comments (0)