8

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?

Sammitch
  • 30,782
  • 7
  • 50
  • 77

2 Answers2

20

I know this is an old question, but as of PHP 7.2 it is provided.

PHP_FLOAT_EPSILON (float)

Smallest representable positive number x, so that x + 1.0 != 1.0. Available as of PHP 7.2.0.

See http://php.net/manual/en/reserved.constants.php

Luke Cousins
  • 2,068
  • 1
  • 20
  • 38
3

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”).

Pascal Cuoq
  • 79,187
  • 7
  • 161
  • 281