2012-01-01 11 views
10

Powiel możliwe:
how to get uniformed random between a, b by a known uniformed random function RANDOM(0,1)Jak wdrożyć losowe (a, b) tylko losowe (0,1)?

W Księdze Wprowadzenie do algorytmów istnieje akcyzowy:

Opisać procedury random (a, b) która wykonuje tylko połączenia losowe (0,1). Jaki jest przewidywany czas trwania procedury, w zależności od a i b? Prawdopodobieństwo wyniku losowego (a, b) powinno być czysto równomiernie rozłożone, ponieważ losowe (0,1)

Dla funkcji losowej wyniki są liczbami całkowitymi z przedziału od a do b włącznie. Na przykład Random (0,1) generuje 0 lub 1; Losowy (a, b) generuje a + 1 a + 2, ..., b

Proponowane rozwiązanie jest tak:

for i = 1 to b-a 
    r = a + Random(0,1) 
return r 

czas odtwarzania jest T = BA

Czy to prawda? Czy wyniki moich rozwiązań są równomiernie dystrybuowane?

Dzięki

Co jeśli moje nowe rozwiązanie jest tak:

r = a 
for i = 1 to b - a //including b-a 
    r += Random(0,1) 
return r 

Jeśli nie jest poprawna, dlaczego R + = Losowy (0,1) sprawia, że ​​R nie równomiernie rozmieszczone?

+3

Twoje rozwiązanie nie jest równomiernie rozmieszczone. Jako przykład, najniższa wartość "a" może być "wyliczona" tylko przez sumę losową (0) + losową (0) + losową (0) + .... jednak prawdopodobieństwo wartości w "środku" jest wyższa, ponieważ można ją obliczyć jako 0 + 0 + 0 + 1 + 1 i 0 + 0 + 1 + 0 + 1 i 1 + 1 + 0 + 0 + 0 i tak dalej. Pomyśl o tym jak rzucanie 2 kostkami. Prawdopodobieństwo uzyskania 2 (1 + 1) lub 12 (6 + 6) jest niższe niż prawdopodobieństwo uzyskania 7 (1 + 6,2 + 5,3 + 4,4 + 3,5 + 2,6 + 1) (osadnicy z catan ftw.;)). – Progman

+0

Twoja druga linia resetuje 'r' za każdym razem. Powinieneś zainicjalizować ją na 'a', a następnie zaktualizować ją w kategoriach samej w pętli. –

Odpowiedz

13

Inni wyjaśnili, dlaczego Twoje rozwiązanie nie działa. Oto poprawne rozwiązanie:

1) Znajdź najmniejszą liczbę, p, taką, że 2^p > b-a.

2) Wykonaj następujący algorytm:

r=0 
for i = 1 to p 
    r = 2*r + Random(0,1) 

3) Jeżeli r jest większa niż b-a, przejdź do kroku 2.

4) Twój wynik jest r+a

Więc spróbujmy Losowo (1,3).
Więc b-a to 2.
2^1 = 2, więc p będą musiały być tak, że 2^p 2 jest większa niż 2.
więc pętla będzie dwa razy.Spróbujmy wszystkie możliwe wyjścia:

00 -> r=0, 0 is not > 2, so we output 0+1 or 1. 
01 -> r=1, 1 is not > 2, so we output 1+1 or 2. 
10 -> r=2, 2 is not > 2, so we output 2+1 or 3. 
11 -> r=3, 3 is > 2, so we repeat. 

Więc 1/4 czasu, wyjście 1. 1/4 wyjścia my czasu 2. 1/4 wyjścia my czasu 3. I 1/4 czas, w którym musimy powtórzyć algorytm po raz drugi. Wygląda dobrze.

Pamiętaj, że jeśli masz to zrobić dużo, dwie optymalizacje są poręczne:

1) W przypadku korzystania z tego samego zakresu dużo, mają klasę, która oblicza p raz, więc nie trzeba obliczyć za każdym razem.

2) Wiele procesorów ma szybkie sposoby wykonywania kroku 1, które nie są wyświetlane w językach wysokiego poziomu. Na przykład procesory x86 mają instrukcję BSR.

+0

Ideą tutaj jest znalezienie maksymalnej liczby bitów potrzebnych do przedstawienia największej liczby, a następnie obrócenie monety dla każdego z tych bitów. –

+0

Tak. A następnie, jeśli jest poza zakresem, powtórz proces. –

+0

Przyszedłem do czegoś podobnego, ale raczej w formie binarnej wyszukiwarki. Dzięki, miło widzieć, że było w porządku. Miał jednak nadzieję na sprytny sposób na zredukowanie problemu z potęgi 2 do dowolnej liczby (i lepszego O-big). – gorlum0

2

Nie, to nie jest właściwe, ta metoda skupi się wokół numeru (a+b)/2. Jest to dwumianowa dystrybucja.

Czy jesteś pewien, że Random(0,1) tworzy liczby całkowite? byłoby bardziej sensowne, gdyby produkował wartości zmiennoprzecinkowe z zakresu od 0 do 1. Następnie rozwiązaniem byłaby transformacja afiniczna, czas działania niezależny od a i b.

Pomysł, który właśnie miałem, na wypadek, gdyby chodziło o wartości całkowite: użyj bisekcji. Na każdym kroku masz zasięg low-high. Jeśli Random(0,1) zwróci 0, następnym zakresem jest low-(low+high)/2, w innym przypadku (low+high)/2-high. Szczegóły i złożoność pozostały do ​​ciebie, ponieważ jest to praca domowa.

To powinno stworzyć (w przybliżeniu) jednolity rozkład.

Edytuj:około to ważne słowo. Jednolity jeśli b-a+1 jest potęgą 2, nie za daleko, jeśli jest blisko, ale ogólnie nie jest wystarczająco dobry. Cóż, to był spontaniczny pomysł, nie można ich wszystkich naprawić.

+0

Oto cytat z książki: Przyjmiemy, że mamy do dyspozycji generator liczb losowych RANDOM. Wywołanie RANDOM (a, b) zwraca liczbę całkowitą między aib, włącznie, przy czym każda taka liczba całkowita jest równie prawdopodobna. Na przykład RANDOM (0, 1) daje 0 z prawdopodobieństwem 1/2 i daje 1 z prawdopodobieństwem 1/2 –

+0

Aha. Racja, w przeciwnym razie byłaby zbyt łatwa. Zapomniałem pierwszej linijki, gdy zobaczyłem tag odrabianiu prac domowych :) –

+0

@DanielFischer To spowoduje tylko dystrybucję w przybliżeniu równomierną. Rozważ (1,3). –

0

Przede wszystkim zakładam, że faktycznie gromadzisz wynik, nie dodając 0 lub 1 do a na każdym kroku. Korzystając z niektórych probabilitów możesz udowodnić, że twoje rozwiązanie nie jest równomiernie dystrybuowane. Szansa, że ​​uzyskana wartość r jest (a + b)/2 jest największa.Na przykład, jeśli a wynosi 0, a b 7, szansa, że ​​otrzymasz wartość 4, jest (kombinacja 4 z 7) podzielona przez 2 podniesiona do potęgi 7. Powodem tego jest to, że bez względu na to, która 4 z 7 wartości to 1 wynik będzie nadal 4.

Szacowany czas działania jest prawidłowy. pseudokod

-1

rozwiązanie powinno wyglądać następująco:

r=a 
for i = 0 to b-a 
    r+=Random(0,1) 
return r 

Jeśli chodzi o równomiernym rozkładzie, przy założeniu, że losowo realizacja to generator liczb losowych jest oparta na doskonale jednolity szanse na uzyskanie 0 lub 1 to 50%. Dlatego otrzymanie numeru, który chcesz, jest wynikiem tego wyboru dokonanego w kółko.

Dla a = 1, b = 5, zostało wybranych 5 opcji.

szanse na uzyskanie 1 obejmuje 5 decyzji same 0, szanse, które wynoszą od 0,5^5 = 3,125%

szanse na uzyskanie 5 obejmuje 5 decyzji, wszystko 1, szanse, które wynoszą od 0,5^5 = 3,125%

Jak widać z powyższego, rozkład nie jest jednolity - szanse dowolnej liczby powinny wynosić 20%.

0

W algorytmie, który utworzyłeś, naprawdę nie jest równo rozłożony.

Wynik "r" zawsze będzie "a" lub "a + 1". To nigdy nie wyjdzie poza to.

To powinno wyglądać mniej więcej tak:

r=0; 
for i=0 to b-a 
    r = a + r + Random(0,1) 

return r; 

Włączając „r” do swojego obliczeń, jesteś tym „przypadkowości” wszystkich poprzednich „dla” przebiegów pętli.

0

Nie, twoje rozwiązanie nie jest poprawne. Ta suma będzie miała rozkład dwumianowy.

Można jednak wygenerować czystą losową sekwencję 0, 1 i traktować ją jako liczbę binarną.

repeat 
    result = a 
    steps = ceiling(log(b - a)) 

    for i = 0 to steps 
    result += (2^i) * Random(0, 1) 
until result <= b 

KennyTM: moje złe.

+0

'2^(i * Losowo (0, 1))'? Czy masz na myśli '(2^i) * Losowe (0, 1)'? – kennytm

1

Przeczytałem inne odpowiedzi. Dla zabawy, oto inny sposób na znalezienie losowej liczby:

Przydziel tablicę z elementami b-a. Ustaw wszystkie wartości na 1. Powtórz po tablicy. Dla każdego niezerowego elementu odwróć monetę, tak jak poprzednio. Jeśli pojawi się 0, ustaw element na 0.

Kiedy po całkowitym iteracji, masz tylko 1 elementem pozostały, masz liczbę losową: a+i gdzie i jest indeksem elementu niezerową (zakładając rozpoczynamy indeksowanie na 0). Wszystkie liczby są równie prawdopodobne. (Będziesz musiał zmierzyć się z przypadkiem, w którym jest remis, ale zostawiam to jako ćwiczenie dla ciebie.)

To by miało O(infinity) ... :) Średnio jednak połowa liczb byłaby wyeliminowana , więc miałby średni czas działania sprawy: log_2 (b-a).

+0

Możesz rzeczywiście wykonać tę pracę w rozsądny sposób i jeśli zrobisz to dobrze, to jest to O (n log n) (gdzie n = b-a).Zasadniczo, chcesz zwiększyć każdy element tablicy, jeśli Random (0,1) wynosi 1, każdy z elementów w biegu uważa się, jeśli jego wartość jest mniejsza od wartości granicznej. Przy każdym przejściu zwiększasz wartość graniczną i jeśli żadne wartości nie są prawidłowe, zmniejsz wartość odcięcia. Kiedy jeden wpis jest ważny, gotowe. –