JavaScript & TypeScript DISCUSSION

Why is 0.1 + 0.2 not 0.3 in JavaScript, and how do I round a reading to 2 decimals?

Started by ghouse floating point precisionIEEE 754toFixed roundingNumber.EPSILONdecimal arithmetic
4 replies 248 views 5 participants
Latest activity · 30 Sep 2026

Why is 0.1 + 0.2 not 0.3 in JavaScript, and how do I round a reading to 2 decimals?

#1

My web dashboard shows a voltage as 3.3000000000000003 after adding two calibration values (1.1 and 2.2), and 0.1 + 0.2 === 0.3 is false. To tidy the display I used Math.round(v * 100) / 100, which mostly works, but 1.005 comes out as 1 instead of 1.01, and (1.005).toFixed(2) gives "1.00" as well.

Why can JavaScript not add simple decimals exactly, why do both rounding methods get 1.005 wrong, and what is a reliable way to round and compare measured values?

Community replies 4

Re: Why is 0.1 + 0.2 not 0.3 in JavaScript, and how do I round a reading to 2 decimals?

#2

Every JavaScript number is an IEEE 754 double: binary floating point with a 53-bit significand. A binary fraction can represent exactly only sums of powers of two, such as 0.5, 0.25 and 0.125. In binary, 0.1 is a repeating fraction, like 1/3 in decimal, so what is stored is the nearest double, 0.1000000000000000055511151231257827.

0.2 and 0.3 are slightly off in the same way, and the sum of the doubles nearest to 0.1 and 0.2 is not the double nearest to 0.3; it prints as 0.30000000000000004. This is not a JavaScript defect. A C double, a Python float and a Java double give the same result. A double carries 15 to 17 significant decimal digits, which is plenty for measurements; the trouble is only in display and exact comparison.

Re: Why is 0.1 + 0.2 not 0.3 in JavaScript, and how do I round a reading to 2 decimals?

#3

On 1.005: the literal is not 1.005 but the nearest double, 1.00499999999999989. The rounding never sees a tie. toFixed(2) correctly rounds the stored value down to 1.00, and 1.005 * 100 evaluates to 100.49999999999999, which Math.round takes to 100.

A common remedy nudges the value by a tiny amount: Math.round((v + Number.EPSILON) * 100) / 100 gives 1.01 for 1.005. It fixes cases like this one, but it is a heuristic. For large values EPSILON, about 2.2e-16, is smaller than the spacing between adjacent doubles and has no effect. For a sensor reading, whether an exact tie displays as 1.00 or 1.01 is below the noise anyway.

Re: Why is 0.1 + 0.2 not 0.3 in JavaScript, and how do I round a reading to 2 decimals?

#4

Separate storage from display. Keep the full-precision number for calculations and round only when formatting. v.toFixed(2) returns a string with exactly two decimals, "3.30"; Number(v.toFixed(2)) converts back to a number and drops trailing zeros. new Intl.NumberFormat('en-US', { maximumFractionDigits: 2 }).format(v) gives at most two decimals, and v.toPrecision(4) works in significant digits.

Do not round intermediate results: average 1,000 samples first and round once at the end. And never use === on computed floats. Compare with a tolerance sized to the quantity, such as Math.abs(a - b) < 0.005 for values shown with two decimals.

Re: Why is 0.1 + 0.2 not 0.3 in JavaScript, and how do I round a reading to 2 decimals?

#5

Where exact decimal arithmetic matters, such as counters or energy totals that must add up, work in integers of the smallest unit: store millivolts or ADC counts and divide only for display. Integers are exact in a double up to 2^53 - 1, which is 9,007,199,254,740,991 (Number.MAX_SAFE_INTEGER); beyond that use BigInt. 3300 mV plus 5 mV is exactly 3305, displayed with (mv / 1000).toFixed(3). This mirrors fixed-point practice in firmware.

Long-running sums drift as well: adding 0.1 ten times gives 0.9999999999999999, and the error grows with the count. Keep an integer tick count and multiply, t = n * 0.1, instead of repeatedly adding the step.

TEP COMMUNITY