Как я могу сгенерировать последовательность чисел, например
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);
Для справки см .:
Например, см.