Как я могу сгенерировать последовательность чисел, например
1 2 4 8 11 12 14 18 …
(плюс 10 каждые 4 номера) со следующими дополнительными требованиями:
$input = 24;
1 2 4 8 11 12 14 18 21 22 24
$input = 20;
1 2 4 8 11 12 14 18
Вот что я пробовал до сих пор:
<?php // sample user input $input = 20; $number = 1; $counter = 0; $array = array(); //conditions while ($counter < 4) { $counter++; array_push($array, $number); $number += $number; } //outputs for ($x = 0; $x < count($array); $x++) { echo $array[$x]; echo " "; }
Код: ( Демо )
function arrayBuilder($max,$num=1){ $array=[]; for($i=0; ($val=($num<<$i%4)+10*floor($i/4))<=$max; ++$i){ $array[]=$val; } return $array; } echo implode(',',arrayBuilder(28)),"\n"; // 1,2,4,8,11,12,14,18,21,22,24,28 echo implode(',',arrayBuilder(28,2)),"\n"; // 2,4,8,16,12,14,18,26,22,24,28 echo implode(',',arrayBuilder(20)),"\n"; // 1,2,4,8,11,12,14,18 echo implode(',',arrayBuilder(24)),"\n"; // 1,2,4,8,11,12,14,18,21,22,24
Этот метод очень похож на ответ localheinz, но использует технику, представленную мне beetlejuice, которая быстрее и безопаснее для PHP. Я только читаю ответы localheinz перед публикацией; это вопрос почти идентичной конвергенции интеллекта. Я просто выполняю краткое изложение с лучшими методами, о которых я могу думать.
Как / Почему это работает без массива lookup или операторов?
arrayBuilder() , вы должны отправить значение $max (представляющее наивысшее возможное значение в возвращаемом массиве) и, при желании, вы можете назначить $num (первое число в возвращаемом массиве), в противном случае значение по умолчанию равно 1 . arrayBuilder() $array объявляется как пустой массив. Это важно, если входные значения (ы) пользователя не допускают одну итерацию в цикле for . Эта строка кода необходима для хорошей практики кодирования, чтобы гарантировать, что ни при каких обстоятельствах не должно появляться уведомление / предупреждение / ошибка. for – это самый сложный цикл в php (так говорится в руководстве ), и его три выражения – идеальный способ упаковки тех методов, которые я использую.
$i=0; это то, что разработчики php все время видят. Это одноразовая декларация $i равная 0 которая возникает только before первой итерации. before каждой итерацией. Я попытаюсь сломать это: (круглые скобки важны для этого выражения, чтобы избежать непредвиденных результатов из-за приоритета оператора
( открыть круглую скобку, чтобы содержать левую сторону оператора сравнения $val= declare $val для использования внутри цикла на каждой итерации ($num<<$i%4) из-за приоритета это то же самое, что и $num<<($i%4) означает: «найдите оставшуюся часть $i деленную на 4, затем используйте побитовый оператор« shift left » для msgstr "умножить $num на 2 для каждого" остатка ". Это очень быстрый способ достижения 4-значного паттерна [don't double],[double once],[double twice],[double three times] чтобы создать: 1,2,4,8 , 2,4,8,16 и т. Д. bitwise operators всегда более эффективны, чем arithmetic operators . + add (не конкатенация в случае возникновения путаницы) 10*floor($i/4) округляют $i разделенные на 4 затем умножаются на 10 так что первые четыре итерации получают бонус 0 , следующие четыре получают 10 , следующие четыре получают 20 и т. Д. ) закрывающая скобка для размещения левой стороны оператора сравнения <=$max допускает итерацию до превышения значения $max . ++$i пред-инкрементирование $i в end каждой итерации. Комплексное решение с использованием цикла while:
$input = 33; $result = [1]; // result array $k = 0; // coeficient $n = 1; while ($n < $input) { $size = count($result); // current array size if ($size < 4) { // filling 1st 4 values (ie 1, 2, 4, 8) $n += $n; $result[] = $n; } if ($size % 4 == 0) { // determining each 4-values sequence $multiplier = 10 * ++$k; } if ($size >= 4) { $n = $multiplier + $result[$size - (4 * $k)]; if ($n >= $input) { break; } $result[] = $n; } } print_r($result);
Выход:
Array ( [0] => 1 [1] => 2 [2] => 4 [3] => 8 [4] => 11 [5] => 12 [6] => 14 [7] => 18 [8] => 21 [9] => 22 [10] => 24 [11] => 28 [12] => 31 [13] => 32 )
При ближайшем рассмотрении каждое значение в последовательности желаемых значений можно рассчитать, добавив соответствующие значения двух последовательностей.
0 0 0 0 10 10 10 10 20 20 20 20
1 2 4 8 1 2 4 8 1 2 4 8
1 2 4 8 11 12 14 18 21 22 24 28
Индекс последовательностей начинается с 0 . В качестве альтернативы, они могут начинаться с 1 , но тогда нам придется вычесть 1 , поэтому, чтобы все было просто, мы начинаем с 0 .
$a = 10 * floor($n / 4);
Функция floor() принимает числовое значение и отсекает фракцию.
Также см. https://en.wikipedia.org/wiki/Floor_and_ceiling_functions .
$b = 2 ** ($n % 4);
Оператор ** объединяет базу с показателем и вычисляет результат подъема базы до степени экспоненты .
В версиях PHP до PHP 5.6 вам придется прибегать к использованию функции pow() , см. http://php.net/manual/en/function.pow.php .
Оператор % объединяет два значения и вычисляет остаток деления первого на последний.
$value = $a + $b;
$input = 20; // sequence a $a = function ($n) { return 10 * floor($n / 4); }; // sequence b $b = function ($n) { return 2 ** ($n % 4); }; // collect values in an array $values = []; // use a for loop, stop looping when value is greater than input for ($n = 0; $input >= $value = $a($n) + $b($n) ; ++$n) { $values[] = $value; } echo implode(' ', $values);
Для справки см .:
Например, см.