Wpis z 01.05.2023, autor Andrzej Mazur · Code in sandbox · Subskrybuj LekcjePHP na Youtube
Używając funkcji rand7(), która zwraca liczbę całkowitą od 1 do 7, zaimplementuj funkcję rand5(), która zwraca liczbę całkowitą od 1 do 5.
Używając funkcji rand7()
, która zwraca liczbę całkowitą od 1 do 7 (włącznie) z jednakowym prawdopodobieństwem, zaimplementuj funkcję, rand5()
, która zwraca liczbę całkowitą od 1 do 5 (włącznie).
(orginał ang.) Using a function rand7() that returns an integer from 1 to 7 (inclusive) with uniform probability, implement a function rand5() that returns an integer from 1 to 5 (inclusive).
Oczywistym nasuwa się trywialne rozwiązanie aby zrobić modulo z funkcji rand7()
:
$result = ((rand7() - 1) % 5) + 1
Ale to podchwytliwe zadanie i nieprawidłowa implentacja, bo nie uzyskamy jednakowego prawdopodobieństwa.
Latwo zauważać że liczby 1 i 2 będą pojawiać się 2 razy częściej,
bo także dla wartości 6 i 7 zwracanych przez rand7()
.
Pewnym pomysłem jest nałożenie funkcji liniowej na wynik losowania:
$result = round(($num - 1) * (4.0 / 6.0)) + 1;
Natomiast i to nie jest dobrym rozwiązaniem. W wyniku zaokrągleń nadliczne będą liczby 2 i 4.
Nie pomoże tez zastąpienie round()
przez floor()
lub ceil()
.
Wciąż pewne wartości będą dwukrotnie bardziej liczne niż inne. Dla ceil()
będą to 3 i 5 a dla floor()
liczby 1 i 3.
Najprostszym i najskuteczniejszym rozwiązaniem jest po prostu odrzucenie wartości z poza oczekiwanego zakresu,
i nakazanie funkcji rand7
ponowne wylosowanie liczb.wartości
Prostą implementację z wykorzystaniem żadko stosowanej pętli do-while znajdziecie poniżej:
function rand5() {
do {
$num = rand7();
} while ($num > 5);
return $num;
}
Jeżeli sam chcesz, sprawdzic powyższe informacje, poniżej przedstawiam cały kod do testu, także do przeprowadzenia jakości wyników,
czyli rozkładu ilościowego wartości zwracanych przez testowana funkcję rand5()
<?php
// Pomocnicza funkcja rand7
function rand7() {
return rand(1, 7);
}
// Poszukiwana funkcja rand5
function rand5() {
do {
$num = rand7();
} while ($num > 5);
return $num;
}
// Testy prawdopodobieństwa
$stat = [];
for($i = 1; $i < 110000; $i++) {
$rr = rand5();
@$stat[$rr]++;
}
ksort($stat);
print_r($stat);
Materiał przygotował dla Was:
Andrzej EZNAWCA Mazur
Zapraszam na moje strony:
LekcjePHP.pl
Eznawca.pl