Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: arytmetyka liczb dużej precyzji - liczby losowe
Forum PHP.pl > Forum > PHP
kufalo
Witam, niestety w bibliotece bc nie ma czegos takiego jak bcrand.
Potrzebuje wylosowac liczbe z przedzialu 0 - x, gdzie x jest to liczba calkowita dodatnia zapisana jako string.
Moze jakies podpowiedzi jak to najwydajniej zrobic w miare krotkim kodem ?
I co wazne aby prawdopodobienstwo otrzymania dowolnej liczby bylo jednakowe dla calej puli liczb.
qqrq
Sprawa jest w sumie dość kłopotliwa - leżeli powiedzmy wiesz ile cyfr (powiedzmy xxxx) ma mieć dana liczba - to przechodzisz pętelką po wszystkich "miejscach cyfr" liczby (po iksach) i dla każdego losujesz cyferkę od 0 do 9. Ilość cyfr dziesiętnych też można losować, ale za słaby z rachunku prawdopodobieństwa jestem, żeby powiedzieć, czy liczba losowana w ten sposób (najpierw losujemy ilość cyfr, potem cyfry po kolei) jest tak samo "losowa" jak ta generowana powiedzmy funkcją mt_rand()...
kufalo
No wlasnie ten sposob jest dobry, ale tylko dla liczb x typu 9, 99, 99, 999

Jezeli przykladowo chce lowocac liczbe z przedzialu 0 - 800 to moge wylosowac Twoim sposobem liczbe z przedzialu 0 - 999, a potem reszte z przelenia (bcmod) przez gorna granice plus jeden.
Niby dziala dobrze, ale prawdopodobienstwa wystapiania liczb nie sa jednakowe, poniewa np 0 osiagamy dla wylosowanego 0 oraz 801.
qqrq
No to wymóżdżyłem coś takiego:

  1. <?php
  2. function BCRand($max)
  3. {
  4.  if (!ctype_digit($max))  // tak jakby ktoś chciał losować nie po liczbie...
  5. return false;
  6.  if ($max<1) // sie rozumie...
  7. return false;
  8.  
  9.  $rand = '';
  10.  $is_max = true; // zmienna sprawdza, czy wszystkie wylosowane dotąd cyferki należą do górnego ogra
    niczenia
  11.  $length = strlen($max);
  12.  
  13.  for ($k=0;$k<$length;$k++)
  14.  {
  15. $rand .= (string)rand(0,($is_max)?$max[$k]:9);
  16. if ($rand[$k] != $max[$k])
  17.  $is_max = false;
  18.  }
  19.  return $rand
  20. }
  21. ?>


Od razu mówię - to tak z głowy, nieprzetestowane, ale zasadę działania tego wszystkiego chyba widać.

Pozdrawiam!
zimi
trochę kiepsko w skrypcie @qqrq z prawdopodobieństwem
trochę lepiej będzie chyba z takim kodem:
  1. <?php
  2. function bcrand($zakres)
  3. {
  4. $wykladnik = 5;
  5. $liczb = strlen($zakres);
  6. $isMax = TRUE;
  7. for($i = 0; $i < $liczb; $i++)
  8. {
  9. if($isMax)
  10. {
  11. $do = (int)substr($zakres, $i, $wykladnik);
  12. $liczba = (string)rand(0, $do);
  13. if(strlen($liczba)==strlen($do))
  14. {
  15. $liczba = $liczba{0};
  16. }
  17. else
  18. {
  19. $liczba = '0';
  20. }
  21. $do=(string)$do;
  22. $isMax = ($liczba==$do{0});
  23. $wydruk .= $liczba;
  24. }
  25. else
  26. {
  27. $wydruk .= rand(0, 9);
  28. }
  29. }
  30. $tnij=0;
  31. while($wydruk{$tnij}=='0') $tnij++;
  32. $wydruk = substr($wydruk, $tnij);
  33. return $wydruk;
  34. }
  35. ?>

ew. zabezpieczenia trzeba sobie dopisać...
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.