How to compare floating-point values safely in PHP

2 Answers

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

 Purpose:
     Demonstrates how to compare floating-point values safely
     using a tolerance (epsilon) instead of the == operator.

 Why not use == ?
     Floating-point numbers are stored as binary approximations.
     Some decimal values cannot be represented exactly, which
     leads to small rounding errors.

 Example:
     0.1 + 0.2 != 0.3

     Although mathematically equal, the actual binary values
     may differ slightly.
====================================================================
*/

/**
 * Compares two floating-point values using a tolerance.
 *
 * Parameters:
 *     $a       First value
 *     $b       Second value
 *     $epsilon Maximum allowed difference
 *
 * Returns:
 *     true  -> Values are considered equal
 *     false -> Values are different
 *
 * This simple approach is suitable for many applications.
 */
function approximatelyEqual(float $a, float $b, float $epsilon): bool
{
    return abs($a - $b) <= $epsilon;
}

/*
 * Classic floating-point precision example.
 */
$x = 0.1 + 0.2;
$y = 0.3;

/*
 * Define an acceptable tolerance.
 * Choose a value appropriate for your application.
 */
$epsilon = 1e-9;

echo "================================================\n";
echo " Safe Floating-Point Comparison in PHP\n";
echo "================================================\n\n";

/*
 * Display many decimal places so precision differences
 * become visible.
 */
printf("x = %.17f\n", $x);
printf("y = %.17f\n", $y);

echo "\n";

/*
 * BAD PRACTICE:
 * Direct comparison using ==.
 *
 * Tiny rounding errors can cause this comparison
 * to produce unexpected results.
 */
if ($x == $y) {
    echo "Direct comparison (==): Equal\n";
} else {
    echo "Direct comparison (==): Not Equal\n";
}

echo "\n";

/*
 * GOOD PRACTICE:
 * Compare using a tolerance (epsilon).
 */
if (approximatelyEqual($x, $y, $epsilon)) {
    echo "approximatelyEqual(): Equal\n";
}


/*
run:

================================================
 Safe Floating-Point Comparison in PHP
================================================

x = 0.30000000000000004
y = 0.29999999999999999

Direct comparison (==): Not Equal

approximatelyEqual(): Equal

*/

 



answered Oct 8 by avibootz
0 votes
// For financial calculations, avoid floating-point numbers
// and use arbitrary-precision solutions such as BCMath:

$result = bcadd('0.1', '0.2', 2);

if (bccomp($result, '0.3', 2) === 0) {
    echo "Equal";
}


/*
run:

Equal

*/

 



answered Oct 8 by avibootz
...