PHP номер между интервалами в зависимости от входной строки

В PHP я могу сделать это:

echo rand(5, 15);

Это даст мне число от 5 до 15, отличающееся каждый раз.

Статический номер в зависимости от входной строки

echo my_static_number(5, 15, 'some/custom_string');

Я все еще хочу число от 5 до 15. Разница в том, что я хочу, чтобы оно вычислялось в зависимости от третьего аргумента, строки.

  • Допускается вывод чисел 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
  • Один и тот же номер каждый раз, пока вызов функции остается неизменным.

Пример из реальной жизни

Изображения в папке:

1.jpg
2.jpg
3.jpg
etc.

Вызов Php:

<img src="<?php echo get_image(1, 15, $url); ?>">
<img src="<?php echo get_image(1, 15, $url); ?>">

Выведите что-то вроде этого:

<img src="7.jpg">
<img src="7.jpg">

Один и тот же номер каждый раз, пока вызов функции одинаков.

2 ответа

Решение

Я ожидаю, что вы строите балансировщик нагрузки.

Здесь вам нужно вычислить хеш из строки и преобразовать его в число. Хорошей псевдослучайной хэш-функции будет достаточно, чтобы получить случайное распределение. Одно из решений может быть таким:

function my_static_number($a, $b, $str) {
    $hash = hash('crc32', $str); // crc32 is probably the fastest here
    $dec = hexdec($hash); // convert hash to a decimal value
    $base = $b + 1 - $a; // +1 is needed to include $b as possible value
    return $a + fmod($dec, $base); // get remainder from $dec / $base
}

Некоторые тесты на детской площадке:

Обновление: может быть небольшое улучшение в скорости, если вы возьмете первые 2 символа $hash вместо этого, а затем использовать $dec % $base вместо fmod:

function my_static_number($a, $b, $str) {
    $hash = substr(hash('crc32', $str), 0, 2); // effectively produces a number between 0 and 255
    $dec = hexdec($hash);
    $base = $b + 1 - $a;
    return $a + $dec % $base;
}

Я сделал тест на случайное распределение, и обе функции работают достаточно хорошо.

Вот о чем я подумал, когда прочитал ваш вопрос:

function my_static_number($min,$max,$seedStr)
{
  $hash   = md5($seedStr);
  $length = strlen($hash);
  $seed   = 1234;
  for ($i=0; $i<$length; $i++) $seed += ord($hash[$i]);
  srand($seed);
  return rand($min,$max);
}


echo my_static_number(5, 15, 'some/custom_strings');

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

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

Эта функция имеет некоторые ограничения:

  • скорость: это не самая быстрая Если это необходимо, вам нужен совершенно другой алгоритм.
  • случайность: наблюдается небольшое снижение случайности выходных данных из-за ограниченного числа начальных значений. Это можно улучшить.

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

function my_static_number($min,$max,$seedStr)
{
  $hash   = md5($seedStr);
  $length = strlen($hash);
  $number = 1234;
  for ($i = 0;$i < $length;$i++) $number += ord($hash[$i]);
  return $min + ($number % ($max-$min));
}

echo my_static_number(5, 15, 'some/custom_string');
Другие вопросы по тегам