Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 279
Sammitch Avatar asked May 23 '14 19:05

Sammitch


People also ask

Why do we never use == to compare floating point numbers?

Because floating point arithmetic is different from real number arithmetic. Bottom line: Never use == to compare two floating point numbers. Here's a simple example: double x = 1.0 / 10.0; double y = x * 10.0; if (y !=

How does Epsilon compare to floats?

Epsilon comparisonsbool isEqual = fabs(f1 – f2) <= epsilon; With this calculation we can express the concept of two floats being close enough that we want to consider them to be equal.

How does PHP calculate float value?

The is_float() function checks whether a variable is of type float or not. This function returns true (1) if the variable is of type float, otherwise it returns false.

What is the value of float Epsilon?

The EPSILON property has a value of approximately 2.2204460492503130808472633361816E-16 , or 2-52. This is the smallest value that can be added to 1 to get a distinct number, because double precision floating point format only has 52 bits to represent the mantissa, and the lowest bit has a significance of 2-52.


2 Answers

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

like image 79
Luke Cousins Avatar answered Oct 09 '22 09:10

Luke Cousins


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

like image 30
Pascal Cuoq Avatar answered Oct 09 '22 09:10

Pascal Cuoq