Инкремент $e
в цикле for
- это скорее бесконечный цикл while(1)
.
Так что вместо неправильного использования инкремента в pow()
, выполните pow
самостоятельно, простоумножение один раз за итерацию.Вызов pow()
может быть довольно дорогим, поэтому выполнение собственного вычисления pow
лучше распределит умножение на каждую итерацию.
Edit: Ниже приведен вариант вашей функции, котораяраспределяет вычисление pow()
по итерации.Кроме того, он выполняет более правильную инициализацию переменной (например, возвращаемое значение не было задано), выдает уведомление, если поменялись местами $min
и $max
, и исправляет это, использует abs
вместо троичной, выдает исключение, если недопустимое значениебыл задан для log()
, переименован в некоторые переменные и сначала добавляется $num
к возвращаемому значению в качестве ключа, чтобы в конце сэкономить операцию array_unique
:
/**
* @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;
}
Если вы чувствуете себя экспериментально, это такжеМожно превратить два цикла (for
+ foreach
) в один, но читаемость кода от этого не выигрывает:
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;
}
Я думаю, если вы позаботитесь о том, чтобы не использовать повторнопеременные (например, параметр функции) и дают им возможность лучше читать имена, улучшение приходит само по себе.