ФорумПрограммированиеPHP для идиотов → Как получить число из строки?

Как получить число из строки?

  • smackthat

    Сообщения: 464 Репутация: N Группа: Адекваты

    Spritz Апрель 3, 2010, 4:13 п.п., спустя 5 дней 16 часов 43 минуты

    перешел к реализации и столкнулся с проблемами: распределение неравномерно, да еще и диапазон не весь входит. Вот сама функция:

    // $str - строка с числами, на основе которой получаем псевдослучайное число
    // функция возвращает псевдослучайное число на основе $str в диапазоне [$min, $max]
    function get_int($str,$min,$max)
    {
    $str=base_convert(md5($str), 16, 10);
    $lenght=mb_strlen($str);
    $num=0;
     
     for($i=0; $i<$lenght; $i++)
     {
         $num+=$str[$i];
         
         if($num>=$min && $num<$max)
             break;
         
         if($num>$max)
             $num/=2;
     }

     return (round($num));
    }


    Проверяю распределение таким кодом:

    $m=array(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);

    for($c=0; $c<20000; $c++)
    {
       // current_url() - возвращает текущий url. Добавляю $c чтобы получить уникальный url
       $str=current_url().$c;
       $rand=get_int($str,1,20)-1;
       
       $m[$rand]+=1;
    }

    echo '<pre>';
    echo print_r($m);
    echo '</pre>';

    В результате получаю:

    Array
    (
       [0] => 6498
       [1] => 6568
       [2] => 3056
       [3] => 616
       [4] => 632
       [5] => 657
       [6] => 681
       [7] => 638
       [8] => 654
       [9] => 0
       [10] => 0
       [11] => 0
       [12] => 0
       [13] => 0
       [14] => 0
       [15] => 0
       [16] => 0
       [17] => 0
       [18] => 0
       [19] => 0
    )
    1

    Помогите допилить код, чтоб распределение нормальное было
  • smackthat

    Сообщения: 464 Репутация: N Группа: Адекваты

    Spritz Апрель 3, 2010, 4:47 п.п., спустя 34 минуты 27 секунд

    Добился такого распределения, которое меня впринципе устраивает:

    Array
    (
       [0] => 517
       [1] => 1001
       [2] => 1068
       [3] => 1019
       [4] => 1071
       [5] => 1056
       [6] => 1023
       [7] => 1106
       [8] => 1011
       [9] => 1078
       [10] => 1099
       [11] => 1024
       [12] => 1003
       [13] => 1069
       [14] => 1063
       [15] => 1039
       [16] => 1067
       [17] => 1071
       [18] => 1065
       [19] => 550
    )
    1

    код:

    function get_int($str)
    {
     $num=base_convert(md5($str),16,10);
     $num/=3.4028236692093846346337460743177e+38;
     return $num;
    }


    $m=array(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);

    for($c=0; $c<20000; $c++)
    {
       $str=current_url().$c;
       $rand=round(get_int($str)*19);
       $m[$rand]+=1;
    }

    echo '<pre>';
    echo print_r($m);
    echo '</pre>';

    непонимаю почему первое и последнее числа меньше остальных. Функцию get_int($str) упростил, теперь она отдает в диапазоне [0,1]. Может кто предложит получше реализацию?
  • Trej Gun

    Сообщения: 5305 Репутация: N Группа: в ухо

    Spritz Апрель 6, 2010, 5:55 п.п., спустя 3 дня 1 час 7 минут

    так а в первом результате то вроде все как положено было…
  • smackthat

    Сообщения: 464 Репутация: N Группа: Адекваты

    Spritz Апрель 9, 2010, 6:11 п.п., спустя 3 дня 16 минут

    дак нет, получается там, что числа 1-2 выпадают наиболее часто, а остальные все реже, а нужно, чтобы все с одинаковой вероятностью выпадали.
  • reserved22

    Сообщения: 3 Репутация: N Группа: Кто попало

    Spritz Фев. 27, 2015, 1:09 п.п., спустя 1784 дня 19 часов 57 минут

    Заранее прошу прощения за некропостинг, зарегистрировался только чтобы ответить в этой теме.
    Хочу предложить универсальное решение по генерированию из строки случайного (но постоянного для нее) числа, с равномерным распределением вероятностей и возможностью задавать диапазон возвращаемых значений, от 0 до N. В итоге функция выглядит так:

    /**
    * Return random integer value (from 0 to N) for string, which is permanently CONST for this string.
    *
    * @param $str
    * @param int $from_zero_to
    * @param int $precision
    *
    * @return int
    */
    function random_const_int($str, $from_zero_to = 9, $precision = 5) {
    $str = (string)$str;
    $num = base_convert(md5($str), 16, 10);
    $num = round($num/3.4028236692093846346337460743177e+38, $precision);
    $rand = round($num * $from_zero_to, $precision);
    return (int)$rand;
    }

    /*
    * TEST with probability distribution
    */
    $m = [];
    for($c = 0; $c < 20000; $c++)
    @$m[random_const_int($c, 25)] += 1;
    ksort($m);
    echo '<pre>'. print_r($m, 1) . '</pre>';
    die;

    Результат выполнения:

    Array
    (
    [0] => 834
    [1] => 839
    [2] => 791
    [3] => 829
    [4] => 802
    [5] => 753
    [6] => 803
    [7] => 776
    [8] => 776
    [9] => 793
    [10] => 763
    [11] => 825
    [12] => 864
    [13] => 830
    [14] => 788
    [15] => 808
    [16] => 834
    [17] => 783
    [18] => 728
    [19] => 807
    [20] => 760
    [21] => 794
    [22] => 810
    [23] => 803
    [24] => 807
    )
  • Sinkler

    Сообщения: 7958 Репутация: N Группа: в ухо

    Spritz Фев. 27, 2015, 1:17 п.п., спустя 8 минут 22 секунды

    @reserved22, можешь ещё где-нибудь отвечать, тут не запрещено)

  • phpdude

    Сообщения: 26646 Репутация: N Группа: в ухо

    Spritz Фев. 27, 2015, 1:45 п.п., спустя 27 минут 27 секунд

    воу воу воу палехче! диффуры еще тут приплетите)

    Сапожник без сапог
  • phpdude

    Сообщения: 26646 Репутация: N Группа: в ухо

    Spritz Фев. 27, 2015, 1:46 п.п., спустя 52 секунды

    предлагаю вариант - считать аски коды символов в строке, делить на 255 и умножать на диапазон. быстро, легко, удобно, стабильно )

    Сапожник без сапог
  • reserved22

    Сообщения: 3 Репутация: N Группа: Кто попало

    Spritz Фев. 27, 2015, 2:16 п.п., спустя 30 минут 9 секунд

    @phpdude никаких диффуров. Была проблема - первый и последний варианты выпадали ровно в 2 раза реже, чем все остальные. Я пофиксил это, и добавил возможность генерировать число из заданного диапазона 0-N. И никаких танцев с кодами символов, все уже работает)
  • phpdude

    Сообщения: 26646 Репутация: N Группа: в ухо

    Spritz Фев. 27, 2015, 3:15 п.п., спустя 59 минут 29 секунд

    @reserved22, md5 от строки != танцы с кодами символов? без танцев с кодами символов в принципе не реально сапоставить какой то стабильный хеш от заданной строки, чтобы он не менялся никогда

    Сапожник без сапог
  • reserved22

    Сообщения: 3 Репутация: N Группа: Кто попало

    Spritz Фев. 27, 2015, 3:44 п.п., спустя 28 минут 17 секунд

    @phpdude, единственный вызов md5 != "считать аски коды символов в строке, делить на 255 и умножать на диапазон". Я имею в виду, что все танцы производятся нативной функцией md5, а не собственными ручками.
  • phpdude

    Сообщения: 26646 Репутация: N Группа: в ухо

    Spritz Фев. 27, 2015, 3:48 п.п., спустя 4 минуты 41 секунду

    @reserved22, ок) не важно ))

    Сапожник без сапог
  • phpdude

    Сообщения: 26646 Репутация: N Группа: в ухо

    Spritz Фев. 27, 2015, 3:48 п.п., спустя 7 секунд

    иди другие топики отвечай!

    Сапожник без сапог

Пожалуйста, авторизуйтесь, чтобы написать комментарий!