2013-04-19 27 views
7

Javascript Math.random() gibt eine Pseudozufallszahl mit "einheitlicher" Verteilung zurück.Generieren einer Zufallszahl mit einer ungleichmäßigen Verteilung

Ich brauche eine Zufallszahl im Bereich [0,1], die nach beiden Seiten verzerrt ist. (Bedeutung, höhere Chance, mehr Zahlen neben 0 oder neben 1)

Idealerweise hätte ich gerne einen Parameter, um diese Kurve einzustellen.

Ich vermute, ich kann tun, um ein solches Ergebnis zu erhalten, aber welche ausgefeiltere Möglichkeiten gibt es, dies zu erreichen?

+0

Nach unten Antwort, Poisson-Verteilungen sind nicht [0,1]. Sie sind [0, unendlich]. Also, was willst du? – djechlin

+0

+1, das ist eine gute Frage mit nicht-triviale Lösung. – Nishanth

+0

@djechlin technisch Poisson-Zufallsvariablen unterstützen {0, ..., ∞}, dies ist wichtig, um Proben aus Poisson-Prozessen über Räume zu ziehen, die eine Poisson-Zufallsvariable basierend auf der zugrunde liegenden Geschwindigkeitsverteilung im [0, ∞) -Raum erzeugen Dies wird normalerweise in Poisson-Prozessen berücksichtigt. Wenn Sie die Gesamtheit dieses Raums betrachten, erhalten Sie eine Poisson-Zufallsvariable Anzahl von Ereignissen mit Mittelwert ∞, die traditionell als gültiger Kantenfall betrachtet wird, in dem Sie die Poisson-Zufallsvariable = ∞ (w.p. = 1) erwarten. – mpacer

Antwort

12

Ich glaube, Sie beta distribution with alpha=beta=0.5

wollen Es ist möglich, einheitliche Zufallszahl an Beta-Verteilung unter Verwendung von inverser kumulativer Verteilung zu transformieren.

unif = Math.random() 

Ich bin nicht vertraut mit javascript, aber das sollte klar sein:

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

PS: Sie viele solche Zahlen und Plot Histogramm enter image description here

bearbeiten erzeugen:

Für die Neigung in Richtung 0, transformieren Sie die beta Werte -

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

enter image description here

Für Richtung 1 Verzerren verwandeln as -

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

enter image description here

+0

Interessant! Ich werde das versuchen. Danke für die Grafik Illustration. Was würde ich tun, wenn ich die Verteilung nur auf einer Seite haben möchte? – OpherV

+1

Nun gibt es Möglichkeiten, die gleichmäßige Verteilung auf eine * beliebige * Verteilung mit der inversen CDF-Methode abzubilden. Ich werde meine Antwort aktualisieren, um die bereits vorhandenen Zahlen in Rechts/Links-Versatz umzuwandeln. – Nishanth

+0

Genau das habe ich gebraucht! Danke einen Haufen – OpherV

2

Ich denke, dass Sie Ihre Frage überdenken müssen. Das Poisson ist eine Zählungsverteilung, die in Bezug auf eine Rate angegeben wird, wie z. B. wie viele Vorkommen von etwas im Durchschnitt pro Zeitperiode angezeigt werden. Es ergibt positive ganze Zahlen, so dass das Ergebnis nicht nur im Bereich [0,1] liegen kann. Kannst du bitte klarstellen was du willst?

Unabhängig davon, ein Poisson mit Rate lambda eines Algorithmus zu erzeugen, ist:

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

wobei "Rand" ist der Funktionsaufruf für einen Uniform (0,1). Ich weiß Javascript nicht, aber das sollte einfach genug für Sie zu implementieren sein.

Als Reaktion auf editierte Frage:

Es gibt verschiedene Distributionen, die Ergebnisse auf einem beschränkten Bereich erzeugen, aber viele von ihnen sind nicht für schwache Nerven, wie die Johnson-Familie oder die Beta-Verteilung.

Eine einfache wäre Dreiecksverteilungen. Sqrt (Rand) ergibt eine Dreiecksverteilung, die gegen 1 gebündelt ist, während (1-Sqrt (1-Rand)) eine gegen Null gebündelte Dreiecksverteilung ergibt.

Ein allgemeinerer Dreieck mit dem Modus (häufigster Wert) bei m (wobei 0 < = m < = 1) mit

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

Note erzeugt werden, daß jeder Aufruf von Rande eine separate Uniform zufällig Nummer, dies wird nicht korrekt sein, wenn Sie einen Wert für rand generieren und durchgängig verwenden.

+0

Sie haben absolut Recht. Ich dachte, dass man darüber nachdenkt, alles rückwärts :) Danke, dass du mich richtig gestellt hast (und in die richtige Richtung!). In jedem Fall, gut zu wissen, in Bezug auf den Algorithmus – OpherV

2

Yoy window.crypto.getRandomValues wo verfügbar

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

var randVal = new Uint8Array(1); 

window.crypto.getRandomValues(randVal); 

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

Auf jsfiddle

verwenden können (wenn das, was für Ihr fragt, ich bin nicht sicher)

Oder vielleicht wie diese

<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); 

auch auf jsfiddle

1

Ich kam gerade mit einem einfacheren Weg Zufallszahl zu erhalten verzerrt zu jede Seite, und die keine Abhängigkeiten hat.

Diese Methode verwendet zwei der regulären Zufallszahlen von Javascript. Der erste Faktor wird mit sich selbst multipliziert (je größer der Exponent, desto größer der Verzerrungseffekt), und der zweite wählt, auf welcher Seite der Verteilung er sich neigt.

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

In diesem Code der Exponent bis 2. Eine Probe Histogramm von 10.000 Ausführungen mit dem Exponenten in 2 wie oben festgelegt ist:

Histogram with exponent 2

mit dem Exponenten 3:

Histogram with exponent 3

Und mit Exponent 10:

+0

Ich bemerke ein mögliches Problem mit dieser Methode. Math.random() erzeugt Zahlen von 0 einschließlich bis 1 exklusiv. Dieses Verfahren kann jedoch Zahlen von 0 bis einschließlich 1 erzeugen.Wenn das ein Problem für Sie ist, könnte eine mögliche Korrektur darin bestehen, die letzte Zeile in 'return 1 - Number.EPSILON - a;' zu ändern. Obwohl ich nicht sicher bin, ob dies jemals einen Wert von etwas weniger als 0 ergeben könnte. – tremby

Verwandte Themen