Reg.ru: домены и хостинг

Крупнейший регистратор и хостинг-провайдер в России.

Более 2 миллионов доменных имен на обслуживании.

Продвижение, почта для домена, решения для бизнеса.

Более 700 тыс. клиентов по всему миру уже сделали свой выбор.

Перейти на сайт->

Бесплатный Курс "Практика HTML5 и CSS3"

Освойте бесплатно пошаговый видеокурс

по основам адаптивной верстки

на HTML5 и CSS3 с полного нуля.

Начать->

Фреймворк Bootstrap: быстрая адаптивная вёрстка

Пошаговый видеокурс по основам адаптивной верстки в фреймворке Bootstrap.

Научитесь верстать просто, быстро и качественно, используя мощный и практичный инструмент.

Верстайте на заказ и получайте деньги.

Получить в подарок->

Бесплатный курс "Сайт на WordPress"

Хотите освоить CMS WordPress?

Получите уроки по дизайну и верстке сайта на WordPress.

Научитесь работать с темами и нарезать макет.

Бесплатный видеокурс по рисованию дизайна сайта, его верстке и установке на CMS WordPress!

Получить в подарок->

*Наведите курсор мыши для приостановки прокрутки.


Генерирование случайных чисел (предсказуемых, в заданном диапазоне, с неравномерным распределением)

В этой статье поговорим о том, как генерировать случайные числа. И не просто случайные, а:

- случайные числа в заданном диапазоне;
- предсказуемые случайные числа;
- случайные числа с неравномерным распределением

Все эти возможности PHP периодически бывают востребованы при создании разных проектов. Итак, начнем.


Генерирование случайных чисел в заданном диапазоне

Первая из трех задач, она же - самая тривиальная - сгенерировать случайное число среди заранее известного нам множества.

Когда это может быть полезно? Когда вы точно знаете, что в текущем месяце, например, 31 день. Или что у вас в ассортименте сейчас 259 позиций товаров. Или когда на сайте у вас 1356 статей, и т.п.

Иными словами, вам надо вычленить что-то одно из ограниченного диапазона.

Решим эту задачу с помощью функции mt_rand():


$lower = 65;
$upper = 97;
// Случайное число в диапазоне от $upper до $lower включительно
$random_number = mt_rand($lower, $upper);

echo $random_number;

Случайные числа пригодятся в самых разных ситуациях:

- можете вывести на страницу случайное изображение;
- получить из БД случайную запись
- сгенерировать уникальный идентификатор сеанса;
- и многое другое..

Как видно из примера, для генерации случайного числа в диапазоне нужно передать функции mt_rand() два аргумента: минимальное и максимальное число, которое может быть возвращено в результате вызова.

В случае вызова mt_rand() без передачи аргументов будет возвращено число в диапазоне от 0 до максимального случайного числа, которое может быть получено вызовом mt_getrandmax().

Забавно то, что генерация по-настоящему случайного числа - непростая задача для бездушной машины. Компьютеры специализируются на методичном выполнении инструкций и алгоритмов - со спонтанностью они справляются значительно хуже:)

В итоге, для того, чтобы компьютер возвращал случайные числа, придется предоставить ему конкретный набор повторяемых команд, а сам факт повторяемости этих команду уже противоречит идее случайности.

Кстати, в PHP есть два генератора случайных чисел — классическая функция rand() и улучшенная mt_rand(). Сокращение «MT» означает «Mersenne Twister» и произошло от имени французского богослова и математика Марена Мерсенна, «вихря Мерсенна» — разновидности генератора, основанного на свойствах простых «чисел Мерсенна».

Функция mt_rand() менее предсказуема (насколько это возможно для четких компьютерных алгоритмов) и работает быстрее, поэтому для наших целей ее использование предпочтительнее.

Двигаемся дальше, и следующей нашей задачей будет...


Генерирование предсказуемых случайных чисел

Данная возможность открывает перед нами широкие возможности по созданию элементов веб-приложений, которые гарантируют нам повторяемость своего поведения.

Пара простых примеров, с которым вы могли столкнуться воочию:

1. Вы оказываетесь на форуме, и вам показывается количество участников онлайн. Допустим, это 224 человека. Неплохо, да? Вы обновляете страницу и видите цифру в 222 человека. Обновляете снова - видите 225 человек. Снова обновляете - 223, и т.д.

Понятно, что нехорошо обманывать своих посетителей, но это частый прием, который позволяет имитировать активный, "живой" форум.

2. Вы попадаете на страницу, где вам предлагают зарегистрироваться на какое-нибудь мероприятие. Вам радостно сообщают (в виде цифр), что на него уже зарегистрировалось 5876 человек.

Вы обновляете страницу и видите, что зарегистрировалось уже 5877 человек, обновили еще раз - уже 5880, еще раз - 5882... Ну и дальше в том же ключе.

Смысл почти такой же - нагнетается атмосфера, что это жутко популярное мероприятие, на которое все валят просто толпой и буквально каждую секунду кто-то на него регистрируется. Обман? Обман. Но так тоже часто делается, чтобы повысить значимость события.

Я надеюсь, что вы не будете применять генерирование предсказуемых чисел для таких "махинаций", но зато будете иметь эти примеры в виду.

Итак, как это будет работать?

Инициализируйте генератор случайных чисел заранее известным значением с использованием функции mt_srand():


function pick_color() {
    $colors = array('red','orange','yellow','blue','green','indigo','violet');
    $i = mt_rand(0, count($colors) - 1);
    return $colors[$i];
}

mt_srand(123);
$first = pick_color();
$second = pick_color();
// Так как mt_srand() передается конкретное значение, каждый раз
// будут выбираться одни и те же цвета: yellow и orange
print "$first это red, а $second это yellow.";

Здесь важно понимать, что в качестве параметра для mt_srand() можно использовать разные значения и именно от этих значений будет зависеть конечный результат случайного выбора. При этом, что для нас и важно - для каждого нового параметра случайная выборка всегда будет воспроизводиться одинаково.

Можете проверить это, передав функции другой параметр (например, 12) после чего снова вернув исходный (т.е. 123).

Наконец, третий момент, который мы рассмотрим, это...


Генерирование случайных чисел с неравномерным распределением

Что такое неравномерное распределение? Это ситуация, когда некоторые случайные числа появляются чаще других случайных чисел. Получается эдакая псевдослучайность, которая имеет очень важное прикладное значение.

Типичный пример - необходимо сделать так, чтобы серия показов рекламных баннеров распределялась пропорционально количеству показов, оставшихся для каждой рекламной кампании.

Для реализации этой не совсем тривиальной задачи PHP не одарил нас специализированной функцией, поэтому стоит воспользоваться проверенным вариантом, написанным народными умельцам (может быть, это сделали вы?:))


// Функция возвращает случайно выбранный ключ из взвешенного набора
function rand_weighted($numbers)
{
    $total = 0;
    foreach ($numbers as $number => $weight)
    {
        $total += $weight;
        $distribution[$number] = $total;
    }

    $rand = mt_rand(0, $total - 1);
    foreach ($distribution as $number => $weights)
    {
        if ($rand < $weights)
        {
            return $number;
        }
    }
}

Представьте, что вместо массива с количеством оставшихся показов у вас есть массив, в котором для каждой рекламы количество элементов соответствует количеству оставшихся показов. Вы можете просто выбрать невзвешенную случайную позицию в массиве, и соответствующая реклама будет отображается на странице.

Но здесь есть одно большое НО. При миллионах оставшихся показов этот метод приведет к огромным затратам памяти.

Вместо этого можно и нужно поступить иначе: вычисляем размер массива (суммируя оставшиеся показы), выбираем случайное число из диапазона с размером предполагаемого массива, после чего по массиву определяем, какая реклама соответствует выбранному числу.


$ads = array('ford' => 12234, // Реклама, оставшиеся показы
             'kia'  => 33424,
             'bmw'  => 16823);

$ad = rand_weighted($ads);

echo $ad;

Пообновляв страницу, вы быстро заметите, что слово "kia" выводится примерно в 2 раза чаще, чем "bmw" и почти в три раза чаще, чем "ford". Задача решена.

На этом сегодня закругляемся. Увидимся в других материалах.

Понравился материал и хотите отблагодарить?
Просто поделитесь с друзьями и коллегами!


Смотрите также:

PHP: Получение информации об объекте или классе, методах, свойствах и наследовании

PHP: Получение информации об объекте или классе, методах, свойствах и наследовании

CodeIgniter: жив или мертв?

CodeIgniter: жив или мертв?

Функции обратного вызова, анонимные функции и механизм замыканий

Функции обратного вызова, анонимные функции и механизм замыканий

Применение функции к каждому элементу массива

Применение функции к каждому элементу массива

Слияние массивов. Преобразование массива в строку

Слияние массивов. Преобразование массива в строку

Деструктор и копирование объектов с помощью метода __clone()

Деструктор и копирование объектов с помощью метода __clone()

Эволюция веб-разработчика или Почему фреймворк - это хорошо?

Эволюция веб-разработчика или Почему фреймворк - это хорошо?

Магические методы в PHP или методы-перехватчики (сеттеры, геттеры и др.)

Магические методы в PHP или методы-перехватчики (сеттеры, геттеры и др.)

PHP: Удаление элементов массива

PHP: Удаление элементов массива

Ключевое слово final (завершенные классы и методы в PHP)

Ключевое слово final (завершенные классы и методы в PHP)

50 классных сервисов, программ и сайтов для веб-разработчиков

50 классных сервисов, программ и сайтов для веб-разработчиков

Наверх