Blog. Just Blog

Быстрый поиск

Введите фрагмент названия статьи для поиска

Генерация случайных значений на PHP с заданной вероятностью

11.01.2019 | Категория: Web-мастеру и не только | Автор: ManHunter
Понадобилась функция, которая возвращает случайный элемент из определенного набора. Вроде бы простейшее решение в одну строчку. Но особенность задачи такова, что элементы должны появляться не просто случайно, а с определенной вероятностью: какие-то чаще, какие-то реже. То есть у каждого значения имеется весовой коэффициент, влияющий на частоту его появления. Например:
  1. // Массив значений и весовых коэффициентов
  2. $data=array(
  3.     'купить'=>50,
  4.     'заказать'=>5,
  5.     'приобрести'=>30,
  6. );
Для такого набора данных чаще всего должно появляться слово "купить", чуть реже "приобрести" и в очень редких случаях может проскакивать вариант "заказать". Готовая функция получилась следующей:
  1. //-------------------------------------------------------------
  2. // Получение случайного значения с заданной вероятностью
  3. //-------------------------------------------------------------
  4. function smart_rand($data) {
  5.     // Пустой массив не обрабатываем
  6.     if (count($data)==0) { return false; }
  7.  
  8.     // Отсортировать массив с сохранением ключей
  9.     arsort($data);
  10.  
  11.     // Сформировать массив с интервалами
  12.     $max_rand=0;
  13.     $weights=array();
  14.     foreach ($data as $key=>$value) {
  15.         $max_rand+=$value;
  16.         $weights[$max_rand]=$key;
  17.     }
  18.  
  19.     // Случайное число от 0 до суммы всех весовых коэффициентов
  20.     $rand=mt_rand(0,$max_rand);
  21.  
  22.     // Найти интервал, в который попадает случайное число
  23.     foreach ($weights as $key=>$value) {
  24.         if ($rand<=$key) {
  25.             break;
  26.         }
  27.     }
  28.     return $value;
  29. }
На входе передается массив значений с весовыми коэффициентами, на выходе одно из значений. Пример использования:
  1. // Вывести 100 вариантов написания
  2. for($i=0$i<100$i++) {
  3.     echo smart_rand($data).' ';
  4. }
Числовые значения весовых коэффициентов могут быть любыми и следовать в произвольном порядке, их количество также ничем не ограничено.

Просмотров: 2018 | Комментариев: 1

Генератор случайных чисел с использованием RANDOM.ORG

25.10.2016 | Категория: Образ мышления: Assembler | Автор: ManHunter

Генератор случайных чисел с использованием RANDOM.ORG

Тема генераторов случайных чисел является одной из основных в криптографии. Использование любых программных генераторов случайных чисел имеет один главный недостаток: последовательность чисел может называться случайной только если между символами, нету зависимости. А любой алгоритм так или иначе подразумевает зависимость от вычислений. Истинно случайные числа получаются только от аппаратных генераторов. Одним из таких генераторов является сайт RANDOM.ORG. По заявлению его владельцев, источником для случайных чисел является атмосферный шум. Не берусь утверждать, так это или нет, но этот сайт пользуется заслуженной популярностью среди разработчиков всего мира.

Читать статью целиком »
Просмотров: 3878 | Комментариев: 11

Генерация последовательности уникальных кодов на PHP

12.10.2013 | Категория: Web-мастеру и не только | Автор: ManHunter
Иногда возникает задача генерации последовательности уникальных кодов по определенному формату. Это могут быть какие-нибудь одноразовые токены, коды лотерейных билетов, серийные номера, scratch-карты, да мало ли чего. Простое использование ГСЧ в этом случае не дает 100% гарантии, так как выдаваемые им значения могут повторяться, а при большом количестве кодов количество повторений будет только расти. Предлагаю вам следующее решение:
  1. // Набор символов для генерации кодов
  2. $str='1234567890ABCDEF';
  3. // Длина кода без учета разделителей
  4. $code_length=16;
  5. // Нужное количество кодов
  6. $codes_count=300000;
  7. // Позиции разделителя (0 - не надо)
  8. $code_separartor=4;
  9.  
  10. $tmp=array();
  11. $str_length=strlen($str)-1;
  12.  
  13. // Цикл до заполнения массива
  14. while (count($tmp)<$codes_count) {
  15.     // Сгенерировать индекс массива
  16.     $code='';
  17.     for ($i=0$i<$code_length$i++){
  18.         // Разделитель можно не добавлять
  19.         if ($i>&& $code_separartor>&& $i%$code_separartor==0) { $code.='-';}
  20.         $code.=substr($strmt_rand(0,$str_length), 1);
  21.     }
  22.     // Или в массив добавится новый элемент, или
  23.     // перепишется поверх уже имеющийся
  24.     $tmp[$code]=1;
  25. }
  26. // Теперь в массиве $codes уникальные коды
  27. $codes=array_keys($tmp);
Коды генерируются гарантированно уникальные (в пределах одной сессии). Это достигается за счет того, что в качестве кода сперва используются ключи массива, а не значения. Даже если какой-либо код будет сгенерирован повторно, то просто перезапишется уже имеющийся элемент массива, а не добавится новый. Отсутствие проверок типа in_array значительно повышает скорость работы генератора. Главный недостаток этого алгоритма в том, что для генерации больших объемов данных потребуется много оперативной памяти. Для особо критичных случаев при выборе символов, составляющих код, лучше использовать не программный ГСЧ, а какой-нибудь аппаратный, чтобы обеспечить максимальную непредсказуемость данных.

Читать статью целиком »
Просмотров: 11544 | Комментариев: 6

Еще один генератор случайных чисел на Ассемблере

17.05.2010 | Категория: Образ мышления: Assembler | Автор: ManHunter
В закромах Родины нашлась реализация еще одного генератора случайных чисел. Он более громоздкий, чем минимальный генератор Парка-Миллера, использует операции с плавающей точкой и кольцевой буфер, но результаты выдает гораздо лучше. Кроме большого кода ему также требуется больше места и в сегменте данных:
  1. section '.data' data readable writeable
  2.  
  3. ; Данные для генератора случайных чисел
  4. JJ      =       10             ; lag 1
  5. KK      =       17             ; lag 2, size of circular buffer
  6. R1      =       19             ; rotate count
  7. R2      =       27             ; rotate count
  8. randp1  dt      1.5            ; used for conversion to float
  9.         dw      0              ; alignment
  10. p1      dd      0              ; pointer in circular buffer
  11. p2      dd      0              ; pointer in circular buffer
  12. randbuf dd      (2*KK) dup(?)  ; circular buffer
Перед первым использованием генератор требуется инициализировать, вызвав функцию WRandomInit с каким-нибудь случайным значением, например, количеством тиков таймера:
  1.         ; Инициализация генератора случайных чисел
  2.         invoke  GetTickCount
  3.         stdcall WRandomInit,eax
  4.         ...
После инициализации генератор можно использовать в двух режимах: генерация одиночного случайного числа размером в два двойных слова (функция WRandom) или генерация случайного числа в заданном диапазоне от 1 до 0FFFFFFFEh (функция WIRandom). Формулировка "одиночное случайное число", наверное, не совсем подходит по смыслу к выполняемому действию, но тавтология "произвольное случайное число" мне показалась хуже.

Читать статью целиком »
Просмотров: 11499 | Комментариев: 10

Генератор случайных чисел на Ассемблере

03.09.2008 | Категория: Образ мышления: Assembler | Автор: ManHunter
При написании программ часто возникает необходимость получить последовательность случайных чисел. В языках высокого уровня существуют штатные функции, а для Ассемблера я использую так называемый "Минимальный генератор Парка-Миллера" (Minimal portable random generator by Park and Miller). От аналогичных алгоритмов его отличает очень малый размер и равномерное распределение получаемых случайных чисел. Математическую модель и описание работы алгоритма можно без труда найти в интернете, поэтому эту информацию я здесь не привожу.
  1. ;---------------------------------------------
  2. ; Park Miller random number algorithm
  3. ; Получить случайное число 0 ... 99999
  4. ; stdcall WRandom
  5. ; на выходе EAX - случайное число 
  6. ;---------------------------------------------
  7. proc    WRandom
  8.         push    edx ecx
  9.         mov     eax,[random_seed]
  10.         xor     edx,edx
  11.         mov     ecx,127773
  12.         div     ecx
  13.         mov     ecx,eax
  14.         mov     eax,16807
  15.         mul     edx
  16.         mov     edx,ecx
  17.         mov     ecx,eax
  18.         mov     eax,2836
  19.         mul     edx
  20.         sub     ecx,eax
  21.         xor     edx,edx
  22.         mov     eax,ecx
  23.         mov     [random_seed],ecx
  24.         mov     ecx,100000
  25.         div     ecx
  26.         mov     eax,edx
  27.         pop     ecx edx
  28.         ret
  29. endp
  30.  
  31. ;---------------------------------------------
  32. ; Получить случайное число в нужном интервале
  33. ; Требуется процедура WRandom
  34. ; stdcall WIRandom,min,max
  35. ; на выходе EAX - случайное число   
  36. ;---------------------------------------------
  37. proc    WIRandom rmin:dword,rmax:dword
  38.         push    edx ecx
  39.         mov     ecx,[rmax]
  40.         sub     ecx,[rmin]
  41.         inc     ecx
  42.         stdcall WRandom
  43.         xor     edx,edx
  44.         div     ecx
  45.         mov     eax,edx
  46.         add     eax,[rmin]
  47.         pop     ecx edx
  48.         ret
  49. endp
  50.  
  51. ;---------------------------------------------
  52. ; Инициализация генератора случайных чисел
  53. ; stdcall WRandomInit 
  54. ;---------------------------------------------
  55. proc    WRandomInit
  56.         push    eax edx
  57.         rdtsc
  58.         xor     eax,edx
  59.         mov     [random_seed],eax
  60.         pop     edx eax
  61.         ret
  62. endp
После небольшой доработки он получил возможность генерировать случайные числа в заданном интервале.

Читать статью целиком »
Просмотров: 31252 | Комментариев: 7

01 02 next
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2025
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.07 сек. / MySQL: 3 (0.0017 сек.) / Память: 4.5 Mb
Наверх