2013-04-19 10 views
7

W języku JavaScript Math.random() zwraca liczbę pseudo losową z "jednolitą" dystrybucją.Generowanie liczby losowej o nierównomiernym rozkładzie

Potrzebuję wygenerować liczbę losową z przedziału [0,1], która jest przekrzywiona na jedną ze stron. (Znaczenie, większa szansa na uzyskanie więcej liczb przy 0 lub obok 1)

Idealnie chciałbym mieć parametr do ustawienia tej krzywej.

Sądzę, że mogę zrobić Math.random^2, aby uzyskać taki wynik, ale jakie są bardziej wyrafinowane sposoby, aby to osiągnąć?

+0

Per poniżej odpowiedź, Poissona nie są [0,1]. Są to [0, nieskończoność]. Więc czego chcesz? – djechlin

+0

+1, jest to dobre pytanie z niebanalnym rozwiązaniem. – Nishanth

+0

@djechlin technicznie Poissona zmienne losowe mają wsparcie ponad {0, ..., ∞}, to ma znaczenie dla myślenia o pobieranie próbek z procesów Poissona na przestrzeni generujących Poissona zmiennej losowej na podstawie stopy bazowej dystrybucji na [0, ∞) przestrzeń zwykle jest to brane pod uwagę w Procesach Poissona. Jeśli wziąć pod uwagę całość tej przestrzeni, masz Poissona losową zmienną liczbę zdarzeń ze średnią ∞, który tradycyjnie jest postrzegane jako ważny przypadku krawędzi, gdzie można oczekiwać Poissona zmienna losowa = ∞ (w.p. = 1). – mpacer

Odpowiedz

12

myślę chcesz beta distribution with alpha=beta=0.5

Jest możliwe, aby przekształcić jednolity liczb losowych do dystrybucji beta stosując odwrotny rozkład łączny.

unif = Math.random() 

nie jestem zaznajomiony z javascript, ale to powinno być jasne:

beta = sin(unif*pi/2)^2 

PS: można generować wiele takich liczb i wykreślić histogram enter image description here

Edit:

Dla wypaczenia w kierunku 0, przekształcić beta wartości jako -

beta_left = (beta < 0.5) ? 2*beta : 2*(1-beta); 

enter image description here

Dla wypaczenia w kierunku 1, przekształcać jak -

beta_right = (beta > 0.5) ? 2*beta-1 : 2*(1-beta)-1; 

enter image description here

+0

Interesujące! Spróbuję tego. Dzięki za ilustrację wykresu. Co powinienem zrobić, jeśli chcę, aby dystrybucja była przekrzywiona tylko z jednej strony? – OpherV

+1

Istnieją sposoby mapowania dystrybucji jednolitej na * dowolną * dystrybucję przy użyciu metody odwrotnego CDF. Zaktualizuję moją odpowiedź, aby przekształcić już liczby w prawe/lewe pochylenie. – Nishanth

+0

Dokładnie tego potrzebowałem! Dzięki pęczku – OpherV

2

Myślę, że należy ponownie przemyśleć swoje pytanie. Poisson jest rozkładem liczenia określanym w kategoriach stopy, np. Ile wystąpień czegoś widzę średnio w danym okresie. Daje dodatnie liczby całkowite, więc wynik nie może znajdować się w zakresie [0,1]. Czy możesz wyjaśnić, czego chcesz?

Niezależnie, w celu wygenerowania Poissona lambda wynosi jeden algorytm:

threshold = Math.exp(-lambda) 
count = 0 
product = 1.0 
while (product *= rand) >= threshold { 
     count += 1 
} 
return count 

gdzie "Rand" oznacza wywołanie funkcji dla jednolitego (0,1). Nie znam javascriptu, ale powinno to być wystarczająco proste, abyś mógł je wdrożyć.

Odpowiadając na edytowanej pytanie:

Istnieje kilka dystrybucje, które generują wyniki na ograniczonym zakresie, ale wiele z nich nie jest dla osób o słabym sercu, takich jak rodzina Johnsona lub dystrybucji Beta.

Łatwo można podzielić na trójkąty. Sqrt (rand) da rozkład trójkąta skupiony w kierunku 1, natomiast (1-Sqrt (1-rand)) da rozkład trójkąta skupiony w kierunku zera.

Bardziej ogólnie trójkąt z trybem (najczęściej value) przy m (gdzie 0 < = M < = 1) mogą być wytwarzane z

if rand <= m 
    return m * Sqrt(rand) 
else 
    return 1 - ((1 - m) * Sqrt(1 - rand)) 

Należy zauważyć, że każde powołanie się na Rand oddzielny równomiernego rozkładu numer, to nie będzie poprawne, jeśli wygenerujesz jedną wartość dla rand i użyjesz go przez cały czas.

+0

Masz absolutną rację. Myślałem, że myślę o tym wszystkim do tyłu :) Dzięki za ustawienie mnie prosto (i we właściwym kierunku!). W każdym razie dobrze wiedzieć o algorytmie – OpherV

2

Dynamika mogą korzystać window.crypto.getRandomValues gdzie dostępne

<div id="result"></div> 

var randVal = new Uint8Array(1); 

window.crypto.getRandomValues(randVal); 

document.getElementById("result").textContent = randVal[0]/255; 

Na jsfiddle

(jeśli to co się z prośbą o, nie jestem pewien)

Albo jak to

<div id="result"></div> 

function poissonRandomNumber(lambda) { 
    var L = Math.exp(-lambda), 
     k = 0, 
     p = 1; 

    do { 
     k = k + 1; 
     p = p * Math.random(); 
    } while (p > L); 

    return k - 1; 
} 

document.getElementById("result").textContent = poissonRandomNumber(100); 

także na jsfiddle

1

właśnie wymyślił prostszy sposób, aby uzyskać liczb losowych przekrzywiony do z każdej strony i która nie ma żadnych zależności.

Metoda ta wykorzystuje dwa regularnych liczb losowych jest obsługa JavaScript. Pierwszy jest mnożony przez siebie (im większy wykładnik, tym większy efekt pochylenia), a drugi wybiera, do której strony rozkładu mają się skosić.

function skewedRandom() { 
    const a = Math.pow(Math.random(), 2); 
    if (Math.random() < 0.5) { 
     return a; 
    } 
    return 1 - a; 
} 

W tym kodzie wykładnik jest ustawiony 2. Próbkę Histogram 10000 wykonaniach z wykładnik przy 2, jak wyżej:

Histogram with exponent 2

z wykładnikiem 3:

Histogram with exponent 3

I z wykładnikiem 10: Histogram with exponent 10

+0

Zauważam możliwy problem z tą metodą. Math.random() generuje liczby od 0 włącznie do 1 wyłącznych. Ta metoda może jednak generować liczby od 0 do 1 włącznie.Jeśli to jest problem dla ciebie, możliwą poprawką może być zmiana ostatniej linii na 'return 1 - Number.EPSILON - a;'. Chociaż nie jestem pewien, czy kiedykolwiek uda się uzyskać wartość nieco mniejszą niż 0. – tremby

Powiązane problemy