JavaScript Number.EPSILON for Float Comparison

In JavaScript, comparing floating-point numbers directly can produce unexpected bugs due to binary rounding limitations inherent to the IEEE 754 standard. Number.EPSILON solves this problem by providing the smallest measurable difference between 1 and the next representable floating-point number. This article explains why direct floating-point comparisons fail in JavaScript, what Number.EPSILON represents, and how to use it to safely perform equality checks.

The Floating-Point Precision Problem

JavaScript represents all numbers using double-precision 64-bit binary format (IEEE 754). Because computers use base-2 (binary) rather than base-10 (decimal), certain decimal fractions cannot be represented with exact precision.

A classic demonstration of this issue is:

console.log(0.1 + 0.2 === 0.3); // false
console.log(0.1 + 0.2);         // 0.30000000000000004

Because 0.1 + 0.2 results in an infinitesimal rounding error, standard equality operators (=== and ==) evaluate the comparison as false.

What is Number.EPSILON?

Introduced in ECMAScript 2015 (ES6), Number.EPSILON is a built-in static property that represents the difference between 1 and the smallest value greater than 1 that can be represented as a Number.

Its value is approximately:

Number.EPSILON; // 2.220446049250313e-16 (or 2^-52)

In numerical computing, this value is often referred to as machine epsilon. It acts as an acceptable margin of error—or tolerance threshold—when comparing the results of floating-point arithmetic.

How to Compare Floating-Point Values Using Number.EPSILON

Instead of checking for exact equality, you check whether the absolute difference between two numbers is smaller than Number.EPSILON. If the difference is smaller than this threshold, the two numbers are considered functionally equal.

Here is a standard helper function:

function areNumbersEqual(a, b) {
  return Math.abs(a - b) < Number.EPSILON;
}

console.log(areNumbersEqual(0.1 + 0.2, 0.3)); // true

Explanation of the Function:

  1. Math.abs(a - b) calculates the positive difference between the two values.
  2. < Number.EPSILON determines whether that difference is within the acceptable precision limit.

Scaling EPSILON for Large Numbers

While Number.EPSILON works reliably for numbers close to 1, calculations involving very large numbers may accumulate rounding errors larger than Number.EPSILON. In such cases, scale the epsilon value relative to the magnitude of the numbers being compared:

function areClose(a, b) {
  return Math.abs(a - b) <= Number.EPSILON * Math.max(Math.abs(a), Math.abs(b));
}

This ensures that the tolerance adjusts proportionally to the scale of the operands, preventing false negatives during high-magnitude calculations.