Search code examples
phpfloating-pointepsilon

Why does PHP not provide an Epsilon constant for floating point comparisons?


After seeing many PHP questions about comparing the equality of floats where the answer is to simply choose an arbitrary value for Epsilon and then do if( abs($a-$b) < 0.000001 ).

The trouble is that Epsilon is typically much smaller than the values people tend to choose [2.22e-16 on my machine] and is actually quite simple to calculate:

$macheps = (float) 1.0;  
do {
    $macheps /= (float) 2.0;
} while( (float) (1.0 + ($macheps/2.0)) != 1.0 );
printf("Epsilon: %0.25f\n", $macheps);

C++ has std::numeric_limits<double>::epsilon(), Python has sys.float_info.epsilon, so why does PHP leave it up in the air?


Solution

  • C++'s std::numeric_limits<double>::epsilon() was never intended to be used in place of 0.000001 in a formula of the style abs($a-$b) < 0.000001. For instance, with most C++ compilation platforms, fabs(x - 2.5) < std::numeric_limits<double>::epsilon() is equivalent to x == 2.5, because std::numeric_limits<double>::epsilon() is a representation of the double definition near 1.

    Some programmers may need to compare floating-point numbers up to some value, but that value has little reason to be related to the definition of the floating-point format near 1, so that's not a good reason to provide that constant in the language. Instead, the value should come either from requirements (“as small as needed”) or by inference (“the floating-point results can be 0.003 from the real result, so fabs(x - 2.5) < 0.003 will never be false if the real result can be 2.5”).