За последние 24 часа нас посетили 22984 программиста и 1234 робота. Сейчас ищут 792 программиста ...

ГПСЧ на РНР (сугубо для самообразования)

Тема в разделе "Решения, алгоритмы", создана пользователем Vladson, 11 мар 2008.

  1. Vladson

    Vladson Старожил

    С нами с:
    4 фев 2006
    Сообщения:
    4.040
    Симпатии:
    26
    Адрес:
    Estonia, Tallinn
    Собственно вот "мой" генератор псевдослучайных чисел.
    (не совсем мой конечно, слизал само собой, но на РНР его переписал я)

    Работает в диапазоне
    rand16() - 0-65535


    И сам по себе прост как 3.1415926.......

    Код (Text):
    1. <?php
    2. /***********************************************************
    3.  *\  \    ___ __        /\     ____   ____  ____  __ |  |
    4.  * \  \  /  /|  |      /  \   |  _ \ /  __>/    \|  ||  |
    5.  *  \  \/  / |  |     / /\ \  | | \ \\_ \_ | || ||   \  |
    6.  *   \    /  |  |__  /  __  \ | |_/ / _\  \| || ||  \   |
    7.  *    \  /   |_____|/__/  \  \|____/ <____/\____/|  ||__|
    8.  *     \/                  \  \                  |  |
    9.  ***********************************************************
    10.  *   Title:  Pseudorandom number generator
    11.  *   Version: 0.0.2
    12.  *
    13.  *   URL:    http://dkflbk.nm.ru/
    14.  *   E-Mail: dkflbk@nm.ru
    15.  ***********************************************************
    16.  *
    17.  *   This program is free software; you can  redistribute
    18.  *   it  and/or  modify  it  under  the  terms of the GNU
    19.  *   General Public License  as  published  by  the  Free
    20.  *   Software Foundation; either version 2 of the License
    21.  *   or  anylater version.
    22.  *
    23.  **********************************************************/
    24.  
    25. Class VLD_Rand {
    26.     var $seed1;
    27.     var $seed2;
    28.     var $seed3;
    29.     function seed($seed1, $seed2, $seed3) {
    30.         $this->seed1 = $seed1;
    31.         $this->seed2 = $seed2;
    32.         $this->seed3 = $seed3;
    33.     }
    34.     function rand16() {
    35.         $a = $this->seed2;
    36.         $b = $this->seed1;
    37.         $b = ($a+$b)&65535;
    38.         $this->seed1 = $a;
    39.         $this->seed2 = $a = $this->seed3;
    40.         $a = ($a+$b)&65535;
    41.         return $this->seed3 = $a = ($a*2 > 65535) ? $a*2-65535 : $a*2;
    42.     }
    43. }
    44. ?>
    Ну и примерчик использования :D
    Код (Text):
    1. <?php
    2. /**
    3.  *  Example
    4. **/
    5. $rnd = new VLD_Rand();
    6. $rnd->seed(1, 2, 3);
    7.  
    8. for($i=0; $i<99; $i++) {
    9.     echo $rnd->rand16().', ';
    10. }
    11. ?>
     
  2. Dagdamor

    Dagdamor Активный пользователь

    С нами с:
    4 фев 2006
    Сообщения:
    2.095
    Симпатии:
    1
    Адрес:
    Барнаул
    Ммм... а почему для генерации 16-значного ты перемножаешь два 8-значных?
    Это же зверски влияет на равномерность распределения результата, в частности, нечетные числа будут выдаваться с вероятностью 1/4, а не 1/2, как должно быть...

    Я тут недавно почитал статью про алгоритм для генерации СЧ под названием "Mersenne Twister" (это как раз тот, который используется в mt_rand). Достаточно несложная идея, просто суперские результаты (какой-то просто невообразимый период), мне очень понравилось.
     
  3. Vladson

    Vladson Старожил

    С нами с:
    4 фев 2006
    Сообщения:
    4.040
    Симпатии:
    26
    Адрес:
    Estonia, Tallinn
    Лично я не перемножаю (сам я его даже не запускал почти использовал кроме как при написании)
    а добавил (уже убрал) эти "перемножения" в последнюю минуту (сам не знаю зачем, может не выспался...)
     
  4. mmaavv

    mmaavv Активный пользователь

    С нами с:
    25 мар 2007
    Сообщения:
    59
    Симпатии:
    0
    А разьве ПХП не может читать из "/dev/random" ?

    А ещё может оказаться так, что система поддерживает аппаратный RNG.
     
  5. Vladson

    Vladson Старожил

    С нами с:
    4 фев 2006
    Сообщения:
    4.040
    Симпатии:
    26
    Адрес:
    Estonia, Tallinn
    mmaavv
    Это генератор не случайных чисел, а псевдо-случайных. (есть и у них свои области применения)

    Опять-же это написано сам не знаю зачем, в РНР есть встроенные функции которые справляются со всем этим "на ура" и ими лучше и пользоваться
     
  6. guest2013

    guest2013 Активный пользователь

    С нами с:
    19 ноя 2007
    Сообщения:
    109
    Симпатии:
    0
    А какой период данной ПСЧ (не диапазон генерируемых чисел, а именно период повторения последовательности)? Зависит ли он от начальных seed1,seed2,seed3?
     
  7. Vladson

    Vladson Старожил

    С нами с:
    4 фев 2006
    Сообщения:
    4.040
    Симпатии:
    26
    Адрес:
    Estonia, Tallinn
    Период не особо большой (конкретных чисел не назову) но зависит на прямую от начальных значений seed1,seed2,seed3 (алгоритм довольно старый, я его вычитал в журнале 92-го года, и уже там писали что он старый)
     
  8. guest2013

    guest2013 Активный пользователь

    С нами с:
    19 ноя 2007
    Сообщения:
    109
    Симпатии:
    0
    А почему бы не использовать более простой алгоритм типа: x(n+1)=A*x(n)+B mod M ?
    При грамотном выборе A и B период данной последовательности будет равен M, да и распределение можно подобрать приемлемым.
     
  9. Vladson

    Vladson Старожил

    С нами с:
    4 фев 2006
    Сообщения:
    4.040
    Симпатии:
    26
    Адрес:
    Estonia, Tallinn
    Просто потому что он не попался под руку, а попался этот.

    Добавлено:
    Для человека мрожет и простой, а вот для процессора очень тяжёлый.
     
  10. guest2013

    guest2013 Активный пользователь

    С нами с:
    19 ноя 2007
    Сообщения:
    109
    Симпатии:
    0
    Пытаюсь разобраться в математике алгоритма...

    Я не совсем понял, где в коде перемножение двух 8-значных?

    Это не ошибка? Именно 65535, а не 65536?
     
  11. Vladson

    Vladson Старожил

    С нами с:
    4 фев 2006
    Сообщения:
    4.040
    Симпатии:
    26
    Адрес:
    Estonia, Tallinn
    убрал (раньше было)
    нет не ошибка именно 65535

    На ассемблере это выглядит так
    Код (Text):
    1. _rand_16:
    2.     push dx
    3.     mov ax,seed1
    4.     mov dx,ax
    5.     mov ax,seed2
    6.     mov seed1,ax
    7.     add ax,dx
    8.     mov dx,ax
    9.     mov ax,seed3
    10.     mov seed2,ax
    11.     add ax,dx
    12.     rcl ax,1
    13.     mov seed3,ax
    14.     pop dx
    15.     ret
     
  12. sword dancer

    sword dancer Активный пользователь

    С нами с:
    17 фев 2008
    Сообщения:
    295
    Симпатии:
    0
    как вам такая психоделика? :-D

    PHP:
    1. <?php
    2.  
    3. ############################
    4. # Лицензионнное соглашение #
    5. #--------------------------#
    6. # Вам   запрещено   читать #
    7. # этот  текст.  Немедленно #
    8. # закройте глаза  во избе- #
    9. # жание   поражения  моска #
    10. ############################
    11.  
    12. # Desu. Desu? Desu!
    13. class Desu {
    14.     var $data;
    15.     function __construct( $props= array() ){
    16.         $this->data= (object)$props;
    17.     }
    18.     function __get( $name ){
    19.         $method= 'get__' . $name;
    20.         if( method_exists( $this, $method ) )
    21.             return $this->{$method}();
    22.         return $this->data->{$name};
    23.     }
    24.     function __set( $name, $value ){
    25.         $method= 'set__' . $name;
    26.         if( method_exists( $this, $method ) )
    27.             return $this->{$method}( $value );
    28.         return $this->data->{$name}= $value;
    29.     }
    30.     function __clone( ){
    31.         $this->data= clone $this->data;
    32.     }
    33. }
    34.  
    35. # Бродяга, блуждающий по индексному массиву
    36. class Stranger extends Desu {
    37.     function __construct( $array ){
    38.         $this->array= $array;
    39.         $this->index= -1;
    40.     }
    41.     function get__haveNext( ){ # есть куда идти?
    42.         return isset( $this->array[ ++$this->index ] );
    43.     }
    44.     function get__current( ){ # а тут чо?
    45.         return $this->array[ $this->index ];
    46.     }
    47. }
    48.  
    49. # Историк, он записывает происходящие события
    50. class Historian extends Desu {
    51.     function __construct( $array= array() ){
    52.         $this->memory= $array;
    53.     }
    54.     function get__tentacle( ){ # Хотим пройтись по памяти? Юзаем щупальцу!
    55.         return new Stranger( $this->memory );
    56.     }
    57.     function push( $values= array() ){ # О! Вспомнил!
    58.         $this->memory= array_merge( array_reverse( $values ), $this->memory );
    59.         return $values;
    60.     }
    61.     function pop( ){ # Гм... забыл...
    62.         return array_shift( $this->memory );
    63.     }
    64. }
    65.  
    66. # Разумное, но тупое как пробка существо
    67. class Mind extends Desu {
    68.     function __construct( $value= null ){
    69.         $this->employers= (object)array();
    70.         $this->value= $value;
    71.         $this->weight= 1;
    72.     }
    73.     function touch( ){ # Щупаем
    74.         ++$this->weight;
    75.     }
    76.     function grow( $years ){ # Прошло десять лет
    77.         $this->weight/= $years;
    78.     }
    79.     function extradite( $value ){ # Выдай-ка мне своего подчинённого, занимающегося вышиванием крестиком
    80.         return @$this->employers->{$value};
    81.     }
    82.     function employ( $memoir, $employer ){ # Вот те новый подчинённый для вышивания крестиком
    83.         $this->employers->{$memoir}= $employer;
    84.     }
    85. }
    86.  
    87. # Моск Нострадамиуса
    88. class Brain {
    89.     function __construct( $memoirs= array() ){
    90.         $this->memory= new Historian( array( 0 ) );
    91.         $this->reason= new Mind( );
    92.         $this->population= 0;
    93.         $this->train( $memoirs );
    94.     }
    95.     function train( $values= array() ){ # Накачиваем моск историей
    96.         foreach( $values as $value ):
    97.             $tentacle= $this->memory->tentacle;
    98.             $mind= $this->reason;
    99.             while( $tentacle->haveNext && ( $employer= $mind->extradite( $tentacle->current ) ) ){
    100.                 $mind->touch();
    101.                 $mind= $employer;
    102.             }
    103.             $memoir= @$tentacle->current;
    104.             if( !isset( $memoir ) ) $memoir= 0;
    105.             if( $value !== $mind->value ) $mind->employ( $memoir, new Mind( $value ) );
    106.             $this->memory->push(array( $value ));
    107.         endforeach;
    108.         $this->population+= count( $values );
    109.     }
    110.     function predict( ){ # Получаем астрологический прогноз на будущее
    111.         $tentacle= $this->memory->tentacle;
    112.         $mind= $this->reason;
    113.         while( $tentacle->haveNext && ( $employer= $mind->extradite( $tentacle->current ) ) )
    114.             $mind= $employer;
    115.         return $mind->value;
    116.     }
    117. }
    118.  
    119. # Бурный Белый Шумный Поток
    120. class WhiteStream extends Desu {
    121.     function __construct( $initial= array() ){
    122.         $this->generator= new Brain( $initial );
    123.     }
    124.     function get__value( ){ # а сейчас какое значение?
    125.         $gen= $this->generator;
    126.         $chit= 1 - $gen->predict();
    127.         $gen->train(array( $chit ));
    128.         return $chit;
    129.     }
    130. }
    131.  
    132. $init= @$_GET[ 'input' ];
    133. $init= $init ? explode( ',', $init ) : array();
    134. $random= new WhiteStream( $init );
    135.  
    136. $stat= array();
    137. for( $i= 1000; $i; --$i ):
    138.     $rnd= $random->value;
    139.     @++$stat[ $rnd ];
    140.     echo $rnd;
    141. endfor;
    142.  
    143. echo '<pre>';
    144. ksort( $stat );
    145. print_r( $stat );
    146.  
    147. ?>
    два вечера угробил :) осталось приделать старение, вымирание при перенаселённости и поддержку любых значений, а не только 0 и 1...
     
  13. antonn

    antonn Активный пользователь

    С нами с:
    10 июн 2007
    Сообщения:
    2.996
    Симпатии:
    0
    guest2013
    65535+1(нулевое) значений для 16 бит, 65536 - это уже следующий разряд, 17й.
     
  14. Vladson

    Vladson Старожил

    С нами с:
    4 фев 2006
    Сообщения:
    4.040
    Симпатии:
    26
    Адрес:
    Estonia, Tallinn
    Нормальный программист никогда не ставит комментариев. Что писалось с трудом, должно пониматься с трудом :D
     
  15. sword dancer

    sword dancer Активный пользователь

    С нами с:
    17 фев 2008
    Сообщения:
    295
    Симпатии:
    0
    да ладно, не так уж с трудом и писалось :)
     
  16. Anonymous

    Anonymous Guest

    sword dancer, юмор местами специфичный, но веселый. (ня!)
     
  17. sword dancer

    sword dancer Активный пользователь

    С нами с:
    17 фев 2008
    Сообщения:
    295
    Симпатии:
    0
    я знаю! сценарии для хентая пишут на пхп! :)
    PHP:
    1. shounen::saw( $tentacle->virgin ) && shounen::comeIn();
    2. $tentacle->shounen->woman;
    3. Daemon::comeIn();
    4. foreach( Daemon::tentacles as $tentacle ) $tentacle->{ rand(2) ? 'man' : 'woman' }
    5. Daemon::force( array( 'Big Ben' => woman ) );
    6. man::explode( 'tentacle', $daemon );
    7. exit( 'happy endo' );
     
  18. Anonymous

    Anonymous Guest

    sword dancer, *пацталом!* А ты не виртуал dark-demon ?
     
  19. sword dancer

    sword dancer Активный пользователь

    С нами с:
    17 фев 2008
    Сообщения:
    295
    Симпатии:
    0
    совершенно случайно - нет.
     
  20. Anonymous

    Anonymous Guest

    Хм... сколько ж их, программирующих анимешников... :)
     
  21. sword dancer

    sword dancer Активный пользователь

    С нами с:
    17 фев 2008
    Сообщения:
    295
    Симпатии:
    0
    а что, есть программисты, которые не любят анимэ? палево! это кодеры обычные! :)
    хороший программист всегда, прежде чем писать код, понаблюдает за классами, свыкнится с объектами, проникнится их чувствами, усвоит взаимоотношения. и только после этого начинается действие!
     
  22. Vladson

    Vladson Старожил

    С нами с:
    4 фев 2006
    Сообщения:
    4.040
    Симпатии:
    26
    Адрес:
    Estonia, Tallinn
    Все, кто называют аниме мультфильмами, - чмо и должны сдохнуть. (с) 50 правил анимешника.
     
  23. Hight

    Hight Старожил
    Команда форума Модератор

    С нами с:
    5 мар 2006
    Сообщения:
    7.153
    Симпатии:
    0
    Адрес:
    из злой параллельной вселенной
    Я называю аниме говном, наверное я должен перед тем как сдохнуть ещё и помучиться как следует да?!
     
  24. Vladson

    Vladson Старожил

    С нами с:
    4 фев 2006
    Сообщения:
    4.040
    Симпатии:
    26
    Адрес:
    Estonia, Tallinn
    Это как минимум :D
     
  25. guest2013

    guest2013 Активный пользователь

    С нами с:
    19 ноя 2007
    Сообщения:
    109
    Симпатии:
    0
    Vladson. ИМХО. Судя по asm
    Код (Text):
    1.  
    2.    add ax,dx
    3.    rcl ax,1
    4.    mov seed3,ax
    Последние две строки должны выглядеть так:
    PHP:
    1. <?
    2. //    $a = ($a+$b)&65535; !!! Теряется Carry Flag
    3. //    return $this->seed3 = $a = ($a*2 > 65535) ? $a*2-65535 : $a*2; // Не то условие проверки
    4.       $a = $a+$b;
    5.       return $this->seed3 = ( $a > 65535 ? $a*2+1 : $a*2) & 65535;
    6. ?>