# php - Compare numeric values (using a threshold/tolerance) from two arrays with matching keys

211

I need to compare database values with post values. If post values (decimal price) are within 2 cents threshold consider values equal. Result is array with 'real' difference. Arrays are consistent: same number of values, same keys.

``````\$db_values =   array( "21" => 10.00, "22" => 20.00, "25" => 3.55);
\$post_values = array( "21" => 9.98,  "22" => 20.01, "25" => 2.55 );
``````

I'm trying to compare Absolute value to my tolerance value -- epsilon (Compare decimals in PHP) and array_udiff:

``````function epsilon_compare (\$v1,\$v2)
{
\$epsilon = 0.02;
\$diff = abs(\$v1 - \$v2);

if (\$diff <= \$epsilon)
{
return 0;
//echo "numbers are equal";
} else {
return 1;
}
}

print_r(array_udiff(\$post_values, \$db_values, "epsilon_compare"));
``````

gives correct result: Array (  => 2.55 )

but when i use different array I get wrong result eg:

``````   \$db_values =   array( "21" => 10.00, "22" => 20.00, "25" => 3.55);
\$post_values = array( "21" => 8.00,  "22" => 20.01, "25" => 2.55 );
``````

In this case it gives:

``````   Array (  => 8  => 20.01  => 2.55 )
``````

Key  => 20.01 is listed but it is within the threshold so it shouldn't be in result set. I think I don't fully understand array_udiff. thanks.

55

#### Solution:

I don't think that udiff does what you think it does. If you print v1 and v2 it will give you the following:

``````v1: 20.01 v2: 9.98
v1: 2.55 v2: 20.01
v1: 20 v2: 10
v1: 3.55 v2: 20
v1: 9.98 v2: 10
v1: 9.98 v2: 20.01
v1: 20.01 v2: 20
v1: 20.01 v2: 2.55
v1: 2.55 v2: 3.55
``````

It makes more comparisons than you think.

You probably need a piece of code that looks something like:

``````function compare_arrays(\$array1, \$array2){
\$result = array();
foreach(\$array1 as \$value => \$outcome){
if(epsilon_compare(\$array1[\$value], \$array2[\$value])){
\$result[\$value] = \$array2[\$value];
}
}
return \$result;
}
``````
794

#### Solution:

The user supplied callback function is used for comparison. It must return an integer less than, equal to, or greater than zero if the first argument is considered to be respectively less than, equal to, or greater than the second.
Your function always returns 1 if the elements are unequal which results in diffrent (wrong) comparisons decisions.

``````<?php
function epsilon_compare (\$v1,\$v2)
{
\$epsilon = 0.02;
\$diff = \$v1 - \$v2;
return abs(\$diff)<=\$epsilon ? 0 : \$diff;
}

\$db_values =   array( "21" => 10.00, "22" => 20.00, "25" => 3.55);
\$post_values = array( "21" => 8.00,  "22" => 20.01, "25" => 2.55 );
print_r(array_udiff(\$post_values, \$db_values, "epsilon_compare"));
``````

prints

``````Array
(
 => 8
 => 2.55
)
``````

edit: using array_udiff_assoc

``````\$db_values = array ( "1" => 7.55, "2" => 5.45, "3" => 5.45, "4" => 64.45, "5" => 54.75, "6" => 30.40, "7" => 56.99, "8" => 10.90, "9" => 60.85, "11" => 3.25, "12" => 13.05, "13" => 5.45, "14" => 8.00, "15" => 5.45, "16" => 13.05, "17" => 4.35 );
\$post_values = array ( "1" => 7.55, "2" => 5.45, "3" => 5.45, "4" => 64.45, "5" => 54.75, "6" => 30.40, "7" => 56.99, "8" => 10.90, "9" => 60.85, "11" => 3.25, "12" => 13.05, "13" => 2.45, "14" => 8.00, "15" => 5.45, "16" => 12.05, "17" => 2.34 );
print_r(array_udiff_assoc(\$post_values, \$db_values, "epsilon_compare"));
``````

prints

``````Array
(
 => 2.45
 => 12.05
 => 2.34
)
``````

People are also looking for solutions to the problem: how to use a string variable from a php file to a javascript in html

Source