# Numeric and percentage deadband calculation

Calculate if the value exceeds percentage <> numeric deadbands of the previous value.

The first function is for percentage. It detects if $value is $deadband% greater or less than $previous. The second is for numeric difference. It detects if the difference between $value and $previous is greater than $deadband.

function percentage_deadband($value,$previous,$deadband) { if($previous==0 || $value==0 ||$previous == $value) { return false; //if previous or value is 0, we can't work. assume false. }$percentage = $value /$previous * 100;
if($percentage > 100){ return$percentage - $deadband > 100;//if percentage - deadband > 100, we know the deadband is exceeded } if($percentage < 100){
return 100 - $percentage >$deadband;//if 100 - percentage is greater than deadband, we know the deadband is exceeded
}
return false;
}

function numeric_deadband($value,$previous,$deadband) { if($previous==0 || $value==0 ||$previous == $value) { return false; } if($previous > $value){ return$previous - $deadband >=$value;
}else{
return $value -$previous >= $deadband; } return false; }  Testing the functions $numeric_deadband = 3;
$numeric_set = [ 0=>['value'=>77,'previous'=>80],//true 1=>['value'=>78,'previous'=>77],//false 2=>['value'=>81,'previous'=>78],//true 3=>['value'=>81,'previous'=>81]//false ]; echo '<strong>numeric set:</strong><br/>'; foreach($numeric_set as $row) { var_dump(numeric_deadband($row['value'],$row['previous'],$numeric_deadband));
echo '<br/>';
}

echo '<br/>';

$percentage_deadband = 10;$percentage_set = [
0=>['value'=>27,'previous'=>39],//true
1=>['value'=>39,'previous'=>40],//false
2=>['value'=>41,'previous'=>28],//true
3=>['value'=>28,'previous'=>31]//false
];
echo '<strong>percentage set:</strong><br/>';
foreach($percentage_set as$row)
{

var_dump(percentage_deadband($row['value'],$row['previous'],$percentage_deadband)); echo '<br/>'; }  They seem to work correctly with my small set of test data, but I am not so great with math. I'd love a second opinion. • Some comments would be nice, for example, in the first function you could specify that $n represents $value as a percentage of $previous. You could also remove the last if statement from the first function - you're returning false either way. You also might want to be more descriptive with your variable named $n - maybe try $percentChange – Brian Hannay Jul 13 '15 at 4:22
• not really related to your question but you might want to use PHPUnit for testing in the future – Marcel Burkhard Jul 14 '15 at 11:32

## 1 Answer

I'm unclear about what is TRUE and what is FALSE (and how you interpret it).

Is it FALSE = when value is greater than previous by more than deadband?
(i.e. value > previous + deadband is NOT OK)
(i.e. value <= previous + deadband is OK)
That's how I did it below, but if you want the opposite, change the "<" sign.


I would change the two functions in one, and give an extra argument (true for numeric, false for percentage):

    function check_deadband($value,$previous,$deadband,$check_numeric) {
if ($value <= 0) { return false; } if ($check_numeric) {
// numeric testing
$difference=abs($previous-$value); return$difference < $deadband; // ex. value: 74, previous: 70 => difference = 4 // difference: 4 < deadband: 3 => false, not ok } else { // percentage testing$percentage=abs(($value -$previous) * 100/$previous); return$percentage < $deadband; // ex. v:111 p:100, (v-p)*100/p:11% < 10% => false, not ok } }  You eliminated the previous=0 or previous=value cases in your example, but I didn't understand why (you can put them back). I also not sure that your percentage formula is corect. If you want the difference in percentage, then (value-previous)*100/previous will give you the right answer. (ex. value = 10, previous=5 => percentage is 100 - correct!) You can check the function with the following testing code: $numeric_deadband = 3;
$percentage_deadband = 10; /// GENERATE RADNOM DATA ex. 5.000 rows$rows_nr=5000;
$min=40;$max=80;
for ($i=0;$i<$rows_nr;$i++) {
$numeric_set[]=array( "value"=>rand($min,$max), "previous" => rand(40,80));$percentage_set[]=array(
"value"=>rand($min,$max),
"previous" => rand(40,80));
}

$time=microtime(true); // just for testing purposes foreach ($numeric_set as $row) { // check NUMERIC set // remove echos after testing echo "NUMERIC >> value:$row[value] vs previous :".
"$row[previous] (deadband:$numeric_deadband) => ";
echo check_deadband(
$row["value"],$row["previous"],
$numeric_deadband, true) ? "true" : "false"; echo "<br/>"; } unset($row);

// CHECK time in miliseconds
echo "<p>Checking deadband for NUMERIC ($rows_nr rows) took:". round((microtime(true)-$time)*1000)." miliseconds</p>";

$time=microtime(true); foreach ($percentage_set as $row) { // check PERCENTAGE set // remove echo after testing echo "PERCENTAGE >> value:$row[value] vs previous:".
"$row[previous] (deadband:$percentage_deadband) => ";
echo check_deadband(
$row["value"],$row["previous"],
$percentage_deadband, false) ? "true" : "false"; echo "<br/>"; } unset($row);

echo "<p>Checking deadband for PERCENTAGE ($rows_nr rows) took:". round((microtime(true)-$time)*1000)." miliseconds</p>";


Hope this works. Feedback would be appreciated!

EDIT: Changed the script to detect both above and below deadband changes.

• it needs to detect both greater than previous by deadband and less than previous by deadband. – r3wt Jul 17 '15 at 14:37
• See modified script - it detects both cases. – verjas Jul 17 '15 at 14:49