2

i have two files: index.php and logspace.php. In logspace.php i have a function logspace that returns an array. I call this function from index.php. Then I want to check if this returned array has certain value but 'in_array' function doesn't work.

Code in index.php:

<?php
include 'logSpace.php';
$tmp=logspace(0.1,10,9);
$Tr=0.1;

if(in_array($Tr,$tmp))
{
    echo 'true';
}
else
{
    echo 'false';
}
?>

I always get 'false' even though value is clearly in the array:

var_dumb($Tr);

float(0.1)

var_dump($tmp);

array(10) { [0]=> float(0.1) [1]=> float(0.16681005372001) [2]=> float(0.27825594022071) [3]=> float(0.46415888336128) [4]=> float(0.77426368268113) [5]=> float(1.2915496650149) [6]=> float(2.1544346900319) [7]=> float(3.5938136638046) [8]=> float(5.9948425031894) [9]=> float(10) }

Code in logSpace.php

function logspace($start,$end,$num)
{
    $arr=array();
    $logMin=log($start);
    $logMax=log($end);
    $delta=($logMax-$logMin)/$num;
    $accDelta=0;

    for($i=0;$i<=$num;$i++)
    {
        $num_i=pow(M_E,$logMin+$accDelta);
        $arr[]=$num_i;
        $accDelta+=$delta;
    }        
return $arr;
}
?>
8
  • 1
    "I" is capital in If. Commented Nov 12, 2013 at 14:52
  • 3
    Possibly floating point precision Commented Nov 12, 2013 at 14:53
  • 2
    @SureshKamrushi: doesn't matter. only PHP variables are case sensitive. functions/language syntax isn't. Commented Nov 12, 2013 at 14:53
  • 1
    This is most likely caused by the floating point, have you tryed storing the numbers as strings? (example: $arr = array("0.1"); echo in_array("0.1",$arr) ? "true" : "false";) Commented Nov 12, 2013 at 14:54
  • 1
    $accDelta+=delta; should be $accDelta+=$delta; and in $accDelta=$0; $0 doesn't exist. i guess it should be $accDelta=0; Commented Nov 12, 2013 at 14:57

1 Answer 1

5

in_array is going to be testing equality at some point, but your values are floating-point numbers. Equality between floats in any computer language is touchy at best, because of limited precision.

1/10 in base-2 is classically compared to 1/3 in base-10. You can't write 1/3 as a decimal using finite precision and be exact (0.3333...), and you have the same problem with 0.1 on a computer. The solution is either avoiding floats entirely (storing values as strings, storing integer multiples of your floats, calculating your float values on-the-fly, etc.), or sticking strictly to inequalities, rather than equality operations.

For example:

$epsilon = 0.00001;
$target_num = 0.1;

foreach ($tmp as $flt)
{
    if ($flt - $epsilon < $target_num && $target_num < $flt + $epsilon)
    {
        return true; // ~0.1 is in $tmp
    }
}
return false; // ~0.1 is not in $tmp
Sign up to request clarification or add additional context in comments.

1 Comment

This is it, thanks. I converted each element of an array to string with $tmp=array_map('strval',$tmp); before calling in_array.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.