How to compare floating-point values safely in JavaScript

2 Answers

0 votes
/*
====================================================================
 Title: Safe Floating-Point Comparison in JavaScript

 Purpose:
     Demonstrates how to compare floating-point values safely
     using tolerance-based comparisons instead of ===.

 Why not use === ?
     JavaScript uses the IEEE 754 double-precision format for
     all numbers. Many decimal values cannot be represented
     exactly in binary.

 Example:
     0.1 + 0.2 !== 0.3

     Although mathematically equal, tiny rounding errors
     produce slightly different values.
====================================================================
*/

/*
 * Function: approximatelyEqual
 *
 * Safely compares two floating-point values using:
 *   1. Absolute tolerance
 *   2. Relative tolerance
 *
 * This approach works well for:
 *   - Numbers close to zero
 *   - Very large numbers
 *   - General-purpose numerical calculations
 *
 * Parameters:
 *   a              First value
 *   b              Second value
 *   absTolerance   Absolute tolerance
 *   relTolerance   Relative tolerance
 *
 * Returns:
 *   true  -> Values are considered equal
 *   false -> Values are different
 */
function approximatelyEqual(
    a,
    b,
    absTolerance = 1e-12,
    relTolerance = 1e-9
) {
    // Calculate the absolute difference.
    const difference = Math.abs(a - b);

    /*
     * Step 1:
     * Handle values that are extremely close to zero.
     */
    if (difference <= absTolerance) {
        return true;
    }

    /*
     * Step 2:
     * Scale tolerance based on the magnitude
     * of the values being compared.
     */
    const largest = Math.max(
        Math.abs(a),
        Math.abs(b)
    );

    return difference <= largest * relTolerance;
}

/*
 * Main program
 */
const x = 0.1 + 0.2;
const y = 0.3;

console.log("================================================");
console.log(" Safe Floating-Point Comparison in JavaScript");
console.log("================================================");
console.log();

/*
 * Display many decimal places so the precision
 * difference becomes visible.
 */
console.log(`x = ${x.toPrecision(17)}`);
console.log(`y = ${y.toPrecision(17)}`);
console.log();

/*
 * BAD PRACTICE:
 * Direct comparison using ===
 */
if (x === y) {
    console.log("Direct comparison (===): Equal");
} else {
    console.log("Direct comparison (===): Not Equal");
}

console.log();

/*
 * GOOD PRACTICE:
 * Compare using a tolerance-based function.
 */
if (approximatelyEqual(x, y)) {
    console.log("approximatelyEqual(): Equal");
} else {
    console.log("approximatelyEqual(): Not Equal");
}


/*
run:

================================================
 Safe Floating-Point Comparison in JavaScript
================================================

x = 0.30000000000000004
y = 0.29999999999999999

Direct comparison (===): Not Equal

approximatelyEqual(): Equal

*/

 



answered 6 days ago by avibootz
0 votes
function approximatelyEqual(a, b, epsilon = 1e-9) {
    return Math.abs(a - b) <= epsilon;
}

/*
 * Main program
 */

// Example values
const x = 0.1 + 0.2;
const y = 0.3;

// Print program title
console.log("================================================");
console.log(" Safe Floating-Point Comparison in JavaScript");
console.log("================================================");
console.log();

// Show full precision
console.log(`x = ${x.toPrecision(17)}`);
console.log(`y = ${y.toPrecision(17)}`);
console.log();

/*
 * BAD PRACTICE:
 * Direct comparison using ===.
 * This may fail because of floating-point rounding errors.
 */
if (x === y) {
    console.log("Direct comparison (===): Equal");
} else {
    console.log("Direct comparison (===): Not Equal");
}

console.log();

/*
 * GOOD PRACTICE:
 * Compare using approximatelyEqual().
 */
if (approximatelyEqual(x, y)) {
    console.log("approximatelyEqual(): Equal");
} else {
    console.log("approximatelyEqual(): Not Equal");
}

console.log();

/*
 * Additional examples
 */
console.log("Additional Tests:");
console.log("-----------------");

console.log(
    "1000000.000000001 vs 1000000.000000002:",
    approximatelyEqual(
        1000000.000000001,
        1000000.000000002
    )
);

console.log(
    "0.000000000001 vs 0:",
    approximatelyEqual(
        0.000000000001,
        0
    )
);

console.log(
    "1.5 vs 2.0:",
    approximatelyEqual(
        1.5,
        2.0
    )
);


/*
run:

================================================
 Safe Floating-Point Comparison in JavaScript
================================================

x = 0.30000000000000004
y = 0.29999999999999999

Direct comparison (===): Not Equal

approximatelyEqual(): Equal

Additional Tests:
-----------------
1000000.000000001 vs 1000000.000000002: true
0.000000000001 vs 0: true
1.5 vs 2.0: false

*/

 



answered 6 days ago by avibootz
...