Finding and removing outliers / anomalies in an array of numbers in PHP - php

I have an array of numbers like this in PHP:
$numbers = [
0.0021030494216614,
0.0019940179461615,
0.0079320972662613,
0.0040485829959514,
0.0079320972662613,
0.0021030494216614,
0.0019940179461615,
0.0079320972662613,
0.0040485829959514,
0.0079320972662613,
0.0021030494216614,
1.1002979145978,
85.230769230769,
6.5833333333333,
0.015673981191223
];
In PHP, I am trying to find the outliers / anomalies in this array.
As you can see, the anomalies are
1.1002979145978,
85.230769230769,
6.5833333333333,
0.015673981191223
I am trying to find and remove the anomalies in any array.
Here is my code
function remove_anomalies($dataset, $magnitude = 1) {
$count = count($dataset);
$mean = array_sum($dataset) / $count;
$deviation = sqrt(array_sum(array_map("sd_square", $dataset, array_fill(0, $count, $mean))) / $count) * $magnitude;
return array_filter($dataset, function($x) use ($mean, $deviation) { return ($x <= $mean + $deviation && $x >= $mean - $deviation); });
}
function sd_square($x, $mean) {
return pow($x - $mean, 2);
}
However, when I put my array of $numbers in, it only gives me [85.230769230769] as the outlier when there are clearly more outliers there.
I have tried fiddling with the $magnitude and that did not improve anything.

The algorithm shown here uses mean absolute deviation (MAD) a robust measure to identify outliers.
All elements whose distance exceeds a multiple of the MAD are continuously removed and the MAD is recalculated.
function median(array $data)
{
if(($count = count($data)) < 1) return false;
sort($data, SORT_NUMERIC);
$mid = (int)($count/2);
if($count % 2) return $data[$mid];
return ($data[$mid] + $data[$mid-1])/2;
}
function mad(array $data)
{
if(($count = count($data)) < 1) return false;
$median = median($data);
$mad = 0.0;
foreach($data as $xi) {
$mad += abs($xi - $median);
}
return $mad/$count;
}
function cleanMedian(array &$data, $fac = 2.0)
{
do{
$unsetCount = 0;
$median = median($data);
$mad = mad($data) * $fac;
//remove all with diff > $mad
foreach($data as $idx => $val){
if(abs($val - $median) > $mad){
unset($data[$idx]);
++$unsetCount;
}
}
} while($unsetCount > 0);
}
How to use:
$data = [
//..
];
cleanMedian($data);
The parameter $fac needs to be experimented with depending on the data.
With the $ fac = 2 you get the desired result.
array (
0 => 0.0021030494216614,
1 => 0.0019940179461615,
2 => 0.0079320972662613,
3 => 0.0040485829959514,
4 => 0.0079320972662613,
5 => 0.0021030494216614,
6 => 0.0019940179461615,
7 => 0.0079320972662613,
8 => 0.0040485829959514,
9 => 0.0079320972662613,
10 => 0.0021030494216614,
)
With fac = 4, the value 0.015673981191223 is included.

Related

Convert String to custom array PHP

i have problem in my function php .
My function php is to check coordinates whether the coordinates are in polygons .
the problem is , i call polygon latlong from database and type data is string and convert to custom array .
this my function
function containsMaps($point1,$value1)
{
$point = preg_split ("/\,/", $point1);
$value = $value1;
foreach(explode('),(',trim($value,'()')) as $single_array){
$sub_array= array();
foreach(explode(',',$single_array) as $sbs_array)
{
$sub_array = array($sbs_array);
}
$polygon = array($sub_array);
}
if($polygon[0] != $polygon[count($polygon)-1])
$polygon[count($polygon)] = $polygon[0];
$j = 0;
$oddNodes = false;
$x = $point[1];
$y = $point[0];
$n = count($polygon);
for ($i = 0; $i < $n; $i++)
{
$j++;
if ($j == $n)
{
$j = 0;
}
if ((($polygon[$i][0] < $y) && ($polygon[$j][0] >= $y)) || (($polygon[$j][0] < $y) && ($polygon[$i][0] >=
$y)))
{
if ($polygon[$i][1] + ($y - $polygon[$i][0]) / ($polygon[$j][0] - $polygon[$i][0]) * ($polygon[$j][1] -
$polygon[$i][1]) < $x)
{
$oddNodes = !$oddNodes;
}
}
}
return $oddNodes;
}
the polygon data from database like this :
(-6.268649975971238, 106.69106266990389),(-6.267711482694832, 106.72625325217928),(-6.288272630052733, 106.72736905112947),(-6.288699201273463, 106.69106266990389)
if i use static data like this , the function working :
$polygon = array(
array(-6.2811957386588855, 106.70141951079609),
array(-6.281142416506361, 106.70432702536823),
array(-6.2781776962328815, 106.70438066954853),
array(-6.2781776962328815, 106.70136586661579),
);
Your code to split the incoming data isn't quite right. This will work:
foreach(explode('),(',trim($value,'()')) as $single_array){
$polygon[] = explode(',',$single_array);
}
Output:
array (
0 =>
array (
0 => '-6.268649975971238',
1 => ' 106.69106266990389',
),
1 =>
array (
0 => '-6.267711482694832',
1 => ' 106.72625325217928',
),
2 =>
array (
0 => '-6.288272630052733',
1 => ' 106.72736905112947',
),
3 =>
array (
0 => '-6.288699201273463',
1 => ' 106.69106266990389',
),
)
Demo on 3v4l.org
Note this will give you string values, if you want floating point values, use code like this:
foreach(explode('),(',trim($value,'()')) as $single_array){
list ($x, $y) = explode(',',$single_array);
$polygon[] = array((double)$x, (double)$y);
}
Demo on 3v4l.org

How to find backward primes within a range of integers?

I'm trying to solve a backward prime question.
Following is the question:
Find all Backwards Read Primes between two positive given numbers (both inclusive), the second one being greater than the first one. The resulting array or the resulting string will be ordered following the natural order of the prime numbers.
Example
backwardsPrime(2, 100) => [13, 17, 31, 37, 71, 73, 79, 97]
backwardsPrime(9900, 10000) => [9923, 9931, 9941, 9967]
I tried doing something like this:
public function backwardPrime()
{
$start = 7000;
$stop = 7100;
$ans = [];
while($start <= $stop)
{
if($start > 10)
{
if($start !== $this->reverse($start))
{
if($this->isPrime($start) && $this->isPrime($this->reverse($start)))
{
array_push($ans, $start);
}
}
}
$start++;
}
return $ans;
}
public function reverse($num)
{
$reverse = 0;
while($num > 0)
{
$reverse = $reverse * 10;
$reverse = $reverse + $num%10;
$num = (int)($num/10);
}
return $reverse;
}
public function isPrime($num)
{
if($num == 1 || $num == 2 || $num == 3)
return true;
elseif ($num%2 == 0 || $num%3 == 0)
return false;
else
{
$i=5;
while($i<=$num/2)
{
if($num%$i===0)
{
return false;
}
$i++;
}
}
return true;
}
I'm able to get the appropriate answer but while doing the same in single function I'm not able to get it:
public function backwardPrimes()
{
$start = 7000;
$stop = 7100;
$ans = [];
while($start <= $stop)
{
$isStartPrime = true;
$isReversePrime = true;
if($start > 10)
{
$reverse = 0;
$num = $start;
while($num > 0)
{
$reverse = $reverse * 10;
$reverse = $reverse + $num%10;
$num = (int)($num/10);
}
if($start !== $reverse)
{
if($start%2 != 0 && $start%3 != 0)
{
$i =5;
while($i<=$start/2)
{
if($start%$i === 0)
{
$isStartPrime = false;
break;
}
$i++;
}
}
if($reverse%2 != 0 && $reverse%3 != 0)
{
$i =5;
while($i<=$reverse/2)
{
if($reverse%$i === 0)
{
$isReversePrime = false;
break;
}
$i++;
}
}
if($isStartPrime && $isReversePrime)
{
array_push($ans, $start);
}
}
}
$start++;
}
return $ans;
}
I don't know where I'm having mistake, guide me.
Thanks.
An emirp ("prime" spelled backwards) is a prime whose (base 10) reversal is also prime, but which is not a palindromic prime. in other words
Backwards Read Primes are primes that when read backwards in base 10 (from right to left) are a different prime. (This rules out primes which are palindromes.)
try this short solution in which I use two helper function reverse and isPrime :
isPrime: Thanks to #Jeff Clayton for his method to test prime numbers, for more information click the link below https://stackoverflow.com/a/24769490/4369087
reverse: that use the php function [strrev()][1], this method take a string a reverse it, we'll use this trick to reverse a number by converting it to a string reverse it and converting back to an integer.
backwardsPrime: this last function's job is itterating over a range of numbers from $min value to $max value and test if the number if a prime number and it's reverse is a prime number as well and it's not a palindrome number if all of those conditions are true then we addit to the result array.
implementation
function isPrime($number)
{
return !preg_match('/^1?$|^(11+?)\1+$/x', str_repeat('1', $number));
}
function reverse($n)
{
return (int) strrev((string) $n);
}
function backwardsPrime($min, $max)
{
$result = [];
foreach(range($min, $max) as $number) {
$reverse = reverse($number);
if($reverse !== $number && isPrime($number) && isPrime($reverse)) {
$result[] = $number;
}
}
return $result;
}
echo "<pre>";
print_r(backwardsPrime(2, 100));
print_r(backwardsPrime(9900, 10000));
output :
Array
(
[0] => 13
[1] => 17
[2] => 31
[3] => 37
[4] => 71
[5] => 73
[6] => 79
[7] => 97
)
Array
(
[0] => 9923
[1] => 9931
[2] => 9941
[3] => 9967
)
you can even optimize the backwardsPrime function like this :
function backwardsPrime($min, $max)
{
$result = [];
foreach(range($min, $max) as $number) {
$reverse = reverse($number);
if($reverse !== $number && !in_array($number, $result) && isPrime($number) && isPrime($reverse)) {
$result[] = $number;
}
}
return $result;
}

Php string with separator to page list

I try to recreate what we see when we printing page on office or adobe.
For example, when you want to print page 1 to 5 you write : 1-5 and if you want to print a page outside you write : 1-5,8
At the moment I explode string by ',' :
1-5 / 8
Then explode each result by '-' and if I've got result I loop from first page to last and create variable with comma :
1,2,3,4,5,8
Finally I explode by ',' and use array unique to erase double value.
It take some times to achieve this especially when there's a lot of '-'.
Maybe someone got a easier solution to so this ?
Thank
Edit :
$pages = "1-4,6-8,14,16,18-20";
$pages_explode = explode(',',$pages);
foreach($pages_explode as $page){
$page_explode = explode('-',$page);
if(!empty($page_explode[1])){
for ($i=$page_explode[0]; $i<=$page_explode[1] ; $i++) {
$page_final .= $i.',';
}
}else{
$page_final .= $page_explode[0].',';
}
}
$page_final = explode(',',$page_final);
$page_final = array_unique ($page_final);
foreach($page_final as $value){
echo $value.'<br>';
}
Is it a code golf challenge?
Well a basic approach seems fine to me :
$input = '1-5,6-12,8';
$patterns = explode(',', $input);
$pages = [];
foreach ($patterns as $pattern) {
if (2 == count($range = explode('-', $pattern))) {
$pages = array_merge($pages, range($range[0], $range[1]));
} else {
$pages[] = (int)$pattern;
}
}
$uniquePages = array_unique($pages);
var_dump($uniquePages);
Outputs :
array (size=12)
0 => int 1
1 => int 2
2 => int 3
3 => int 4
4 => int 5
5 => int 6
6 => int 7
7 => int 8
8 => int 9
9 => int 10
10 => int 11
11 => int 12
Having to remove duplicates suggests that you have overlapping ranges in your strings.
Eg: 1-5,2-9,7-15,8,10
You seems to process all these without considering the overlapping areas and finally attempt to remove duplicates by the expensive array_unique function.
Your code should instead remember the minimum and maximum of the resulting range and not process anything that overlaps this range.
Following is a sample code which demonstrates the idea. But its certainly faster than the code you have suggested in your question. You should add parts there to process additional types of delimiters, if any, in your requirement.
<?php
$ranges = "1-5,3-7,6-10,8,11";
$min = 10000;
$max = -1;
$numbers = array(); //Your numbers go here
//Just a utility function to generate numbers from any range and update margins
function generateNumbers($minVal, $maxVal) {
global $min, $max, $numbers;
for ($i = $minVal; $i <= $maxVal; $i++) {
array_push($numbers, $i);
if ($i < $min)
$min = $i;
if ($i > $max)
$max = $i;
}
}
//Seperate ranges
$sets = explode(",", $ranges);
//Go through each range
foreach($sets as $aSet) {
//Extract the range or get individual numbers
$range = explode("-", $aSet);
if (count($range) == 1) { //its an individual number. So check margins and insert
$aSet = intval($aSet);
if ($aSet < $min){
array_push($numbers, $aSet);
$min = $aSet;
}
if ($aSet > $max){
array_push($numbers, $aSet);
$max = $aSet;
}
continue; // <----- For single numbers it ends here
}
//Its a range
$rangeLow = intval($range[0]);
$rangeHigh = intval($range[1]);
//Adjusting numbers to omit cases when ranges fall right on the margins
if ($rangeLow == $min){
$rangeLow++;
}
else
if ($rangeLow == $max) {
$rangeLow--;
}
if ($rangeHigh == $min){
$rangeHigh++;
}
else
if ($rangeHigh == $max) {
$rangeHigh--;
}
//Check if below or above the generated range
if (($rangeLow < $min && $rangeHigh < $min) || ($rangeLow > $max && $rangeHigh > $max)) {
generateNumbers($rangeLow, $rangeHigh);
};
//Check if across the lower edge of the generated range
if ($rangeLow < $min && $rangeHigh > $min && $rangeHigh < $max) {
generateNumbers($rangeLow, $min - 1);
};
//Check if across the upper edge of the generated range
if ($rangeLow > $min && $rangeLow < $max && $rangeHigh > $max) {
generateNumbers($max + 1, $rangeHigh);
};
}
//Now just sort the array
print_r($numbers);
?>

How do I get box plot key numbers from an array in PHP?

Say I have an array with values like:
$values = array(48,30,97,61,34,40,51,33,1);
And I want the values to be able to plot a box plot like follows:
$box_plot_values = array(
'lower_outlier' => 1,
'min' => 8,
'q1' => 32,
'median' => 40,
'q3' => 56,
'max' => 80,
'higher_outlier' => 97,
);
How would I do this in PHP?
function box_plot_values($array)
{
$return = array(
'lower_outlier' => 0,
'min' => 0,
'q1' => 0,
'median' => 0,
'q3' => 0,
'max' => 0,
'higher_outlier' => 0,
);
$array_count = count($array);
sort($array, SORT_NUMERIC);
$return['min'] = $array[0];
$return['lower_outlier'] = $return['min'];
$return['max'] = $array[$array_count - 1];
$return['higher_outlier'] = $return['max'];
$middle_index = floor($array_count / 2);
$return['median'] = $array[$middle_index]; // Assume an odd # of items
$lower_values = array();
$higher_values = array();
// If we have an even number of values, we need some special rules
if ($array_count % 2 == 0)
{
// Handle the even case by averaging the middle 2 items
$return['median'] = round(($return['median'] + $array[$middle_index - 1]) / 2);
foreach ($array as $idx => $value)
{
if ($idx < ($middle_index - 1)) $lower_values[] = $value; // We need to remove both of the values we used for the median from the lower values
elseif ($idx > $middle_index) $higher_values[] = $value;
}
}
else
{
foreach ($array as $idx => $value)
{
if ($idx < $middle_index) $lower_values[] = $value;
elseif ($idx > $middle_index) $higher_values[] = $value;
}
}
$lower_values_count = count($lower_values);
$lower_middle_index = floor($lower_values_count / 2);
$return['q1'] = $lower_values[$lower_middle_index];
if ($lower_values_count % 2 == 0)
$return['q1'] = round(($return['q1'] + $lower_values[$lower_middle_index - 1]) / 2);
$higher_values_count = count($higher_values);
$higher_middle_index = floor($higher_values_count / 2);
$return['q3'] = $higher_values[$higher_middle_index];
if ($higher_values_count % 2 == 0)
$return['q3'] = round(($return['q3'] + $higher_values[$higher_middle_index - 1]) / 2);
// Check if min and max should be capped
$iqr = $return['q3'] - $return['q1']; // Calculate the Inner Quartile Range (iqr)
if ($return['q1'] > $iqr) $return['min'] = $return['q1'] - $iqr;
if ($return['max'] - $return['q3'] > $iqr) $return['max'] = $return['q3'] + $iqr;
return $return;
}
Lilleman's code is brilliant. I really appreciate his way to deal with median and q1/q3. If I were answering this first, I would be cope with odd and even amount of values in a harder but unnecessary way. I mean useing if 4 times for 4 different situationgs of mode( count( values ) , 4 ). But his way is just neat and tidy. I really admires his work.
I would like to make some improvemenets about max, min, higher_outliers and lower_outliers. Because q1 - 1.5*IQR is only the lower bound, we should find the least value that greater than this bound as the 'min'. This is the same for 'max'. Also, there might be more than one outliers. So I would like to make some changes based on Lilleman's work. Thanks.
function box_plot_values($array)
{
$return = array(
'lower_outlier' => 0,
'min' => 0,
'q1' => 0,
'median' => 0,
'q3' => 0,
'max' => 0,
'higher_outlier' => 0,
);
$array_count = count($array);
sort($array, SORT_NUMERIC);
$return['min'] = $array[0];
$return['lower_outlier'] = array();
$return['max'] = $array[$array_count - 1];
$return['higher_outlier'] = array();
$middle_index = floor($array_count / 2);
$return['median'] = $array[$middle_index]; // Assume an odd # of items
$lower_values = array();
$higher_values = array();
// If we have an even number of values, we need some special rules
if ($array_count % 2 == 0)
{
// Handle the even case by averaging the middle 2 items
$return['median'] = round(($return['median'] + $array[$middle_index - 1]) / 2);
foreach ($array as $idx => $value)
{
if ($idx < ($middle_index - 1)) $lower_values[] = $value; // We need to remove both of the values we used for the median from the lower values
elseif ($idx > $middle_index) $higher_values[] = $value;
}
}
else
{
foreach ($array as $idx => $value)
{
if ($idx < $middle_index) $lower_values[] = $value;
elseif ($idx > $middle_index) $higher_values[] = $value;
}
}
$lower_values_count = count($lower_values);
$lower_middle_index = floor($lower_values_count / 2);
$return['q1'] = $lower_values[$lower_middle_index];
if ($lower_values_count % 2 == 0)
$return['q1'] = round(($return['q1'] + $lower_values[$lower_middle_index - 1]) / 2);
$higher_values_count = count($higher_values);
$higher_middle_index = floor($higher_values_count / 2);
$return['q3'] = $higher_values[$higher_middle_index];
if ($higher_values_count % 2 == 0)
$return['q3'] = round(($return['q3'] + $higher_values[$higher_middle_index - 1]) / 2);
// Check if min and max should be capped
$iqr = $return['q3'] - $return['q1']; // Calculate the Inner Quartile Range (iqr)
$return['min'] = $return['q1'] - 1.5*$iqr; // This ( q1 - 1.5*IQR ) is actually the lower bound,
// We must compare every value in the lower half to this.
// Those less than the bound are outliers, whereas
// The least one that greater than this bound is the 'min'
// for the boxplot.
foreach( $lower_values as $idx => $value )
{
if( $value < $return['min'] ) // when values are less than the bound
{
$return['lower_outlier'][$idx] = $value ; // keep the index here seems unnecessary
// but those who are interested in which values are outliers
// can take advantage of this and asort to identify the outliers
}else
{
$return['min'] = $value; // when values that greater than the bound
break; // we should break the loop to keep the 'min' as the least that greater than the bound
}
}
$return['max'] = $return['q3'] + 1.5*$iqr; // This ( q3 + 1.5*IQR ) is the same as previous.
foreach( array_reverse($higher_values) as $idx => $value )
{
if( $value > $return['max'] )
{
$return['higher_outlier'][$idx] = $value ;
}else
{
$return['max'] = $value;
break;
}
}
return $return;
}
I wish this could be helpful for those who would be interested in this issue. And Pls add comment to me if there is a better way to know which values are the outliers. Thanks!
I have a different solution for calculating the lower and higher whiskers. Like ShaoE's solution it finds the least value greater or equal than the lower bound (Q1 - 1.5 * IQR) and vice versa for the higher bound.
I use array_filter which iterates over an array, passing values to a callback function and returns an array with only the values for which the callback gives true (see php.net's array_filter manual). In this case values greater than the lower bound are returned and used as input for min which itself returns the least value.
// get lower whisker
$whiskerMin = min(array_filter($array, function($value) use($quartile1, $iqr) {
return $value >= $quartile1 - 1.5 * $iqr;
} ));
// get higher whisker vice versa
$whiskerMax = max(array_filter($array, function($value) use($quartile3, $iqr) {
return $value <= $quartile3 + 1.5 * $iqr;
} ));
Note that it ignores outliers and I only tested it with positive values.

Generating a range with irregular steps. Optimized

Does PHP have existing functionality for irregular step ranges, is there a common solution to provide this functionality, or how can the following function be optimized?
The first function is the function I am concerned about. The second function is a real world use case that generates an array to populate values for a function that outputs a select dropdown for HTML.
<?php
function range_multistep($min, $max, Array $steps, $jmp = 10) {
$steps = array_unique($steps);
sort($steps, SORT_NUMERIC);
$bigstep = ($jmp > 0) ? $jmp : $jmp * -1;
$e = ($min > 0) ? floor(log($min, $bigstep)) : 0;
for (; ; $e++) {
foreach ($steps as $step) {
$jump = pow($bigstep, $e);
$num = $step * $jump;
if ($num > $max) {
break 2;
} elseif ($num >= $min) {
$arr[] = $num;
}
}
}
$arr = array_unique($arr);
sort($arr, SORT_NUMERIC);
return $arr;
}
function prices() {
$price_steps = range_multistep(50, 100000, array(5, 10, 25));
$prev_step = 0;
foreach ($price_steps as $price) {
$price_str = '$' . $prev_step . ' - $' . ($price - 1);
$price_arr[] = $price_str;
$prev_step = $price;
}
$price_arr[] = '$' . end($price_steps) . "+";
return $price_arr;
}
print_r(prices());
The result of the previous:
Array
(
[0] => $0 - $49
[1] => $50 - $99
[2] => $100 - $249
[3] => $250 - $499
[4] => $500 - $999
[5] => $1000 - $2499
[6] => $2500 - $4999
[7] => $5000 - $9999
[8] => $10000 - $24999
[9] => $25000 - $49999
[10] => $50000 - $99999
[11] => $100000+
)
Repeated addition is best replaced by multiplication, and repeated multiplication is best replaced by raising to powers -- which you've done.
I see nothing here that requires improvement assuming you don't need "bulletproof" behavior in the face of $jmp = 1 or $min >= $max badly-behaved inputs.
The $e incrementor in the for loop is more of a while(1) endless loop.
So instead misusing the incrementor in pow(), do the pow on your own by just multiplying once per iteration. Calling pow() can be pretty expensive, so doing the pow calculation your own would better distribute the multiplication onto each iteration.
Edit: The following is a variant of your function that distributes the pow() calculation over the iteration. Additionally it does more proper variable initialisation (the return value was not set for example), gives notice if $min and $max are swapped and corrects that, uses abs instead of your ternary, throws an exception if an invalid value was given for log(), renamed some variables and add $num to the return value as key first to spare the array_unique operation at the end:
/**
* #param int $min
* #param int $max
* #param array $steps
* #param int $jmp
* #return array range
*/
function range_multistep($min, $max, Array $steps, $jmp = 10) {
$range = array();
if (!$steps) return $range;
if ($min < $max) {
trigger_error(__FUNCTION__.'(): Minima and Maxima mal-aligned.', E_USER_NOTICE);
list($max, $min) = array($min, $max);
}
$steps = array_unique($steps);
sort($steps, SORT_NUMERIC);
$bigstep = abs($jmp);
if ($bigstep === 0) {
throw new InvalidArgumentException(sprintf('Value %d is invalid for jmp', $jmp));
}
$initExponent = ($min > 0) ? floor(log($min, $bigstep)) : 0;
for ($multiplier = pow($bigstep, $initExponent); ; $multiplier *= $bigstep) {
foreach ($steps as $step) {
$num = $step * $multiplier;
if ($num > $max) {
break 2;
} elseif ($num >= $min) {
$range[$num] = 1;
}
}
}
$range = array_keys($range);
sort($range, SORT_NUMERIC);
return $range;
}
In case you feel experimental, it's also possible to turn the two loops (for+foreach) into one, but the readability of the code does not benefit from it:
for(
$multiplier = pow($bigstep, $initExponent),
$step = reset($steps)
;
$num = $step * $multiplier,
$num <= $max
;
# infinite array iterator:
($step=next($steps))?:
(
$step=reset($steps)
# with reset expression:
AND $multiplier *= $bigstep
)
){
if ($num >= $min)
$range[$num] = 1;
}
I think if you take care to not re-use variables (like the function parameter) and give them better to read names, improvement comes on it's own.

Categories