Detailed explanation
In JavaScript, 0.1 + 0.2 !== 0.3 evaluates to true because ordinary Number values use IEEE 754 binary64 floating-point representation. This format stores numbers with finite precision in binary, not decimal. Just as one-third has an endless decimal expansion, fractions such as one-tenth and one-fifth have endless binary expansions. JavaScript therefore stores the nearest representable approximations to 0.1 and 0.2. This is a consequence of the number format, not a JavaScript-specific arithmetic bug.
A binary64 value has a sign bit, 11 exponent bits, and 52 explicitly stored fraction bits, providing 53 bits of significant precision for normal values through an implicit leading bit. When JavaScript adds the stored approximations of 0.1 and 0.2, it rounds the result to a representable binary64 value. That result is 0.30000000000000004, while the literal 0.3 is converted to a different, adjacent representable value. Strict equality does not allow a tolerance, so these distinct numeric values compare unequal. Using loose equality would not fix this because both operands already have the same type.
For approximate calculations, compare the absolute difference against a tolerance suitable for the problem: Math.abs(0.1 + 0.2 - 0.3) < 1e-9 is true. Number.EPSILON is the gap between 1 and the next larger representable Number; it is not a universal error limit. Floating-point spacing grows with magnitude, so general comparisons often combine an absolute tolerance near zero with a relative tolerance scaled to the operands. The acceptable tolerance should reflect the application's units, accuracy requirements, and accumulated calculation error.
For money, prefer integer minor units, such as paise, when the required precision is fixed: add 10 and 20 paise rather than fractional rupee amounts. The example (0.1 * 100 + 0.2 * 100) / 100 happens to produce 0.3, but multiplying arbitrary decimal inputs by 100 does not guarantee exact integers. Parse decimal amounts carefully, define rounding rules, and keep Number-based integers within the safe range. For more complex decimal calculations, use a suitable decimal library. Interviewers look for this distinction between approximate measurement arithmetic and deliberately exact financial arithmetic.
Key points to remember
- JavaScript Number uses IEEE 754 binary64; many decimal fractions cannot be represented exactly.
- The computed sum and the literal 0.3 become distinct representable values, so strict equality fails.
- Use domain-appropriate tolerances for approximate comparisons rather than blindly choosing Number.EPSILON.
- For fixed-precision money, calculate in integer minor units with explicit parsing and rounding rules.
- Formatting a result changes its presentation, not the precision of the underlying arithmetic.
Common mistakes candidates make
- Claiming that every decimal is inexact; fractions such as 0.5 and 0.25 are exactly representable in binary.
- Assuming == or a universal Number.EPSILON threshold fixes all floating-point comparisons.
- Treating multiplication by 100 as a guaranteed conversion to exact money values without handling rounding or safe-integer limits.
Likely follow-up questions
Does toFixed() solve the problem?
No; toFixed() produces a string rounded to a specified number of decimal places, which is useful for display. Converting that string back to Number still uses binary floating-point representation.
How can you compare numbers across different magnitudes?
For finite numbers, a common test is Math.abs(a - b) <= Math.max(absTol, relTol * Math.max(Math.abs(a), Math.abs(b))). Choose both tolerances for the application, and handle NaN and infinities explicitly if they are possible inputs.
Can BigInt be used for money?
BigInt can store exact integer minor units beyond Number.MAX_SAFE_INTEGER, which is 2^53 - 1. It does not represent fractional values, so you must manage scale and rounding explicitly; BigInt division truncates towards zero.
Interview tip: Explain binary approximation first, demonstrate the unequal result, then distinguish tolerance-based comparisons from integer-based money calculations.
