1

I've come across a weird/interesting issue while working with a range where the step value was set to .1.

Here's a simple version of the code that just checks if a float value is within an array:

$start =  0;
$end = 1;

$range = range( $start, $end, .1);

//print_r($range);

$find = 0.7;

if( in_array( $find, $range, true ) ){
    echo "in array";
}else{
    echo "not in array";
}

In the above snippet, it would output "not in array", though 0.7 of course exists in the range. If you try changing the value to find to 0.5 for example, it will now find the value. Why is that the case?

This happens with multiple different values whether its 0.x or 1.x, here are some examples:

  • 0.1 - Finds it (whether cast as float or not)
  • 0.2 - Finds it (whether cast as float or not)
  • 0.3 - Doesn't find it (whether cast as float or not)
  • 0.4 - Doesn't find it (whether cast as float or not)
  • 0.5 - Finds it (whether cast as float or not)
  • 0.6 - Doesn't find it (whether cast as float or not)
  • 0.7 - Doesn't find it (whether cast as float or not)

 

  • 1.0 - Finds it (whether cast as float or not)
  • 1.1 - Finds it (whether cast as float or not)
  • 1.2 - Doesn't find it (whether cast as float or not)
  • 1.3 - Finds it (whether cast as float or not)
  • 1.4 - Doesn't find it (whether cast as float or not)

I've tried explicitly casting the value of $find as a float; thinking it was something to do with datatypes but no dice.

What am I missing? Why is in in_array() failing to see that the value is in the array? I've tried without setting its strict parameter to true which still doesn't make a difference.

Uriahs Victor
  • 1,049
  • 14
  • 32
  • Thank you, the issue was fixed by casting the values of the range as a string as recommended here: https://stackoverflow.com/a/19932638/4484799 – Uriahs Victor Sep 16 '22 at 00:06
  • You cannot compare two floating point values for equivalence because unless the values are calculated _exactly_ the same by the _exact_ same process, they will likely differ by a value so small that most string representations will not print it, but they differ nonetheless. If you want to check floats for equivalence use `abs($a-$b) < $epsilon` where `$epsilon` is a value small enough as to be considered inconsequential for that purpose. See the "Is floating point math broken?" duplicate that I just tacked onto the question. – Sammitch Sep 16 '22 at 00:28
  • @Sammitch, the constant is PHP_FLOAT_EPSILON (Available as of PHP 7.2.0.) – Ken Lee Sep 16 '22 at 00:44
  • @KenLee Yes, but it's not terribly useful unless you're comparing numbers on the same scale as `1.0`. I asked a question about this ages ago and started a whole argument about how you can/cannot choose a "proper" epsilon without a lot of work defining the bounds of the comparison itself. – Sammitch Sep 16 '22 at 01:43

0 Answers0