Tak i nie, w zależności od tego, co rozumiesz przez „jedyny sposób”. Tak, ponieważ nie ma metody, która gwarantowałaby zakończenie, najlepszym, co możesz zrobić (dla ogólnych wartości i ), jest algorytm, który kończy się z prawdopodobieństwem 1. Nie, dzięki czemu „marnotrawstwo” jest tak małe jak chceszR.NR
Dlaczego gwarantowane zakończenie jest ogólnie niemożliwe
Załóżmy, że masz silnik obliczeniowy (deterministyczny maszynę Turinga czy cokolwiek pływa łodzią), plus wyrocznię, który generuje losowe elementy -elementowe zestawu . Celem jest, aby wygenerować element -elementowe zestawu . Moc twojego silnika zależy tylko od sekwencji wartości zwracanych przez wyrocznię; jest funkcją tej potencjalnie nieskończonej sekwencji .[ 0 .. R - 1 ] N [ 0 , N - 1 ] f ( r 0 , r 1 , r 2 , … )R[0..R−1]N[0,N−1]f(r0,r1,r2,…)
Załóżmy, że twój silnik woła wyrocznię co najwyżej razy. Mogą istnieć ślady, dla których wyrocznia jest nazywana mniej niż razy; jeśli tak, wywołanie dodatkowego czasu wyroczni, aby zawsze było wywoływane dokładnie razy, nie zmienia wyniku. Zatem bez utraty ogólności zakładamy, że wyrocznia nazywana jest dokładnie razy. Zatem prawdopodobieństwo wyniku jest liczbą sekwencji takich, że . Ponieważ wyrocznia jest jednorodnym generatorem losowym, każda sekwencja jest równoważna i ma prawdopodobieństwo . Stąd prawdopodobieństwo każdego wyniku ma postaćm m m x ( r 0 , … , r m - 1 ) f ( r 0 , … , r m - 1 ) = x 1 / R m A / R m A 0 R mmmmmx(r0,…,rm−1)f(r0,…,rm−1)=x1/RmA/Rmgdzie jest liczbą całkowitą od do .A0Rm
Jeśli dzieli na część , możesz wygenerować równomierny rozkład na elementów, wywołując generator losowy razy (pozostawia się to jako ćwiczenie dla czytelnika). W przeciwnym razie jest to niemożliwe: nie ma sposobu, aby uzyskać wynik z prawdopodobieństwem . Zauważ, że warunek jest równoważny stwierdzeniu, że wszystkie czynniki pierwsze są również czynnikami (jest to bardziej liberalne niż to, co napisałeś w pytaniu; na przykład możesz wybrać losowy element spośród 4 z 6-stronnym fair umrzeć, mimo że 4 nie dzieli 6).R m m N m 1 / N N RNRmmNm1/NNR
Zmniejszenie ilości odpadów
W swojej strategii, gdy , nie musisz ponownie losować od razu. Intuicyjnie pozostało trochę entropii w którą możesz zachować w miksie.[ kr≥kN[kN..R−1]
Załóżmy, że przez cały czas będziesz generował losowe liczby poniżej , a ty generujesz ich liczby naraz, wykonując losowania. Jeśli wykonasz proste próbkowanie odrzucenia dla tej zgrupowanej generacji, marnotrawstwo nad losuje to , tj. Reszta podzielone przez liczbę losowań. Może to być tak mały jak . Kiedy i są pierwszymi pierwszymi, możesz zmniejszyć odpady dowolnie, wybierając odpowiednio duże wartości . Dla ogólnych wartości iu d d R d - kNudd RdmodNugcd(R,N)RNdRNgcd(R,N)N/gcd(R,N)Rd−kNudRdmodNugcd(R,N)RNdRN, obliczenia są bardziej skomplikowane, ponieważ musisz wziąć pod uwagę generowanie i osobno, ale znowu możesz zmniejszyć odpady dowolnie, używając wystarczająco dużych grup.gcd(R,N)N/gcd(R,N)
W praktyce, nawet przy stosunkowo nieefektywnych liczbach losowych (np. W kryptografii), rzadko warto robić nic prócz prostego próbkowania odrzucenia, chyba że jest małe. Na przykład w kryptografii, gdzie jest zwykle potęgą 2, a jest zwykle setkami lub tysiącami bitów, jednolite generowanie liczb losowych zwykle przebiega przez próbkowanie z bezpośrednim odrzuceniem w pożądanym zakresie.R NNRN