Zufälliges Fließkomma-Double im Inclusive-Bereich
Können wir leicht random floating-point-zahlen in einem gewünschten Bereich [X,Y)
(beachten Sie, dass X ist inclusive und Y exklusiv), mit die unten aufgeführte Funktion, da Math.random()
(und die meisten Pseudo-zufälligen Zahl-Generatoren, AFAIK) produzieren zahlen in [0,1)
:
function randomInRange(min, max) {
return Math.random() * (max-min) + min;
}
//Notice that we can get "min" exactly but never "max".
Wie kann man eine zufällige Zahl in einem gewünschten Bereich inclusive an beiden Grenzen, also [X,Y]
?
Ich nehme an, wir könnten die "Schrittweite" unser Wert von Math.random()
(oder gleichwertig) von "Rollen" die bits eines IEE-754 floating point double precision um den maximal möglichen Wert von 1,0 aber genau das scheint wie ein Schmerz zu bekommen Recht, vor allem in Sprachen schlecht geeignet für die bit-manipulation. Gibt es einen einfacheren Weg?
(Nebenbei, warum Zufallszahlen-Generatoren erzeugen zahlen in [0,1)
statt [0,1]
?)
[Bearbeiten] Bitte beachten Sie, dass ich keine müssen für diese und ich bin mir voll bewusst, dass die Unterscheidung kleinlich ist. Einfach nur neugierig und hoffen auf einige interessante Antworten. Fühlen Sie sich frei, um die Abstimmung zu schließen, wenn diese Frage unangebracht ist.
InformationsquelleAutor der Frage maerics | 2012-03-15
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich glaube, es gibt viel bessere Entscheidung, aber diese sollte funktionieren 🙂
InformationsquelleAutor der Antwort Alex L
First off, es gibt ein problem in Ihrem code: Versuchen
randomInRange(0,5e-324)
oder geben Sie einfachMath.random()*5e-324
in Ihrem browser die JavaScript-Konsole.Sogar ohne überlauf/Unterlauf/denorms, ist es schwierig, Grund, zuverlässig zu floating point ops. Nach ein bisschen Graben, finde ich ein Gegenbeispiel:
Ist es einfacher zu erklären, warum dies geschieht, mit a=253 und b=0,5: 253-1 ist die nächste Darstellbare Zahl nach unten. Die Standardeinstellung ("Runde auf die nächste gerade Zahl") Runde 253-0.5 (da 253 ist "noch" [LSB = 0] und 253-1 ist, "ungerade" [LSB = 1]), so subtrahieren Sie
b
bekommen und 253multiplizieren (253-1, und fügen Sieb
253 wieder.Zur Beantwortung Ihrer zweiten Frage: Da die zugrunde liegende PRNG fast immer generiert eine zufällige Zahl im Intervall [0,2n-1], d.h. es erzeugt zufällige bits. Es ist sehr einfach wählen Sie einen geeigneten n (die bits, die Präzision in Ihre floating-point-Darstellung) und dividieren durch 2n und erhalten eine vorhersehbare Verteilung. Beachten Sie, dass einige zahlen in
[0,1)
dass Sie nie erzeugen mit dieser Methode (alles in (0,2-53), mit IEEE-doubles).Es bedeutet auch, dass Sie tun können
a[Math.floor(Math.random()*a.length)]
und sich keine sorgen über überlauf (Hausaufgaben: Im IEEE-Binär-Gleitkommazahl, die beweisen, dassb < 1
implizierta*b < a
für positive integera
).Andere nette Sache ist, die man sich denken kann jedes zufällige Ausgabe x, stellvertretend für ein Intervall [x,x+2-53) (die nicht-so-nette Sache ist, dass der Durchschnittliche Wert der zurückgegeben wird, etwas weniger als 0,5). Wenn man wieder in [0,1], tun Sie zurück, die Endpunkte mit der gleichen Wahrscheinlichkeit als alles andere, oder sollte Sie nur die Hälfte der Wahrscheinlichkeit, weil Sie nur für das halbe Intervall als alles andere?
Antwort auf die einfachere Frage der Rückgabe eine Zahl in [0,1], die Methode effektiv unten erzeugt eine ganze Zahl [0,2n] (durch generieren eine ganze Zahl in [0,2n+1-1] und werfen es Weg, wenn es zu groß ist) und dividieren durch 2n:
Die Kommentare, die implizieren, base 2, aber ich denke die Annahmen sind also:
Beachten Sie, dass die Zufallszahlen werden immer generiert, in Paaren: der eine in der
while
(a) ist immer gefolgt von entweder der einen in dieif
oder die am Ende (b). Es ist ziemlich einfach zu überprüfen, ist es sinnvoll, durch die Berücksichtigung eines PRNG, der gibt entweder 0 oder 0,5:a=0 b=0
: return 0a=0 b=0.5
: return 0.5a=0.5 b=0
: 1 zurücka=0.5 b=0.5
: loopProbleme:
InformationsquelleAutor der Antwort tc.
Meine Lösung für dieses problem war schon immer die Verwendung der folgenden anstelle der oberen Schranke.
oder
Also würde der code so Aussehen:
oder
Diesen einfach Schritten Ihre Obere Grenze durch das kleinste Doppelzimmer (
Double.MIN_VALUE
), so dass Ihre Obere Grenze als eine Möglichkeit, in die zufällige Berechnung.Dies ist ein guter Weg, um darüber zu gehen, weil Sie nicht verzerren die Wahrscheinlichkeiten zu Gunsten von jeden eine Nummer.
Der einzige Fall, würde dies nicht funktionieren, wo Ihre Obere Grenze ist gleich
Double.MAX_VALUE
InformationsquelleAutor der Antwort MetaMilo
Wählen Sie einfach Ihre halb-offenen Intervall etwas größer, so dass, dass Ihre gewählte geschlossenes Intervall ist eine Teilmenge. Dann, halten Sie die Generierung der zufälligen variable, bis es landet, in der besagten geschlossenen Intervall.
Beispiel: Wenn du etwas möchtest, uniform in [3,8], dann immer wieder regenerieren, eine einheitliche Zufallsvariable in [3,9), bis es passiert, um land in [3,8].
Hinweis: Die Menge der Zeiten, die Sie erzeugen, der halb geöffneten R. V. ist die zufällige und potenziell unendlich, aber man kann sich damit die erwartete Anzahl der Anrufe, die anders als in der Nähe von 1, wie Sie möchten, und ich glaube nicht, dass es existiert eine Lösung, die keine potenziell rufen Sie unendlich viele Male.
InformationsquelleAutor der Antwort Berry
Angesichts der "sehr große" Anzahl von Werten zwischen 0 und 1, ist es wirklich wichtig? Die Chancen eigentlich schlagen 1 winzig sind, also ist es sehr unwahrscheinlich, um einen signifikanten Unterschied zu alles, was Sie tun.
InformationsquelleAutor der Antwort Jon Skeet
Was wäre eine situation, wo Sie BRAUCHEN würde, eine floating-point-Wert, inklusive der oberen Grenze? Für Ganzzahlen ich verstehen, aber für einen Schwimmer, den Unterschied zwischen inklusive und exklusive ist, was gefällt 1,0 e-32.
InformationsquelleAutor der Antwort Mike Schachter
Denken Sie an es auf diese Weise. Wenn Sie sich vorstellen, dass floating-point-zahlen beliebiger Genauigkeit, die Chancen, genau
min
null sind. So sind die Chancenmax
. Ich lasse Sie ziehen Sie Ihre eigenen Abschluss.Diesem 'problem' ist äquivalent zu einem zufälligen Punkt auf der reellen Achse zwischen 0 und 1. Es gibt keine "inklusive" und "exklusive".
InformationsquelleAutor der Antwort Kendall Frey
Die Frage ist ähnlich zu Fragen, was ist der floating-point-Zahl direkt vor der 1.0? Es ist so ein floating point Zahl, aber es ist einer in 2^24 (IEEE
float
) oder eine in 2^53 (für einedouble
).Der Unterschied ist in der Praxis vernachlässigbar.
InformationsquelleAutor der Antwort wallyk
Ich bin ziemlich weniger erlebt, Also ich bin auch auf der Suche nach Lösungen.
Dies ist mein grober Gedanke:
Zufallszahlen-Generatoren erzeugen zahlen in [0,1) anstelle von [0,1],
da [0,1) ist eine Einheit der Länge, die verfolgt werden können [1,2) und so weiter, ohne überlappende...
Für random[x,y],
Sie können dies tun:
Wo alle Werte in [x,y] hat die gleiche Möglichkeit, ausgewählt zu werden, und kann u erreichen y jetzt.
Bitte lassen Sie mich wissen, wenn dies nicht funktioniert, oder hat potentielle Probleme.
DANK~
InformationsquelleAutor der Antwort Starringeye
InformationsquelleAutor der Antwort ivan.a.bovin
Math.round()
helfen werden, gehören der gebundene Wert. Wenn Sie0 <= value < 1
(1 exklusiv), dannMath.round(value * 100) /100
zurück0 <= value <= 1
(1 inklusive). Ein Hinweis hier ist, dass der Wert jetzt nur 2 Ziffern in Ihrer Dezimalstelle. Wenn Sie möchten, 3-stellig, versuchenMath.round(value * 1000) /1000
und so weiter. Die folgende Funktion hat einen weiteren parameter, das ist die Anzahl der Ziffern, Dezimalstelle, - rief ich, als Präzision:InformationsquelleAutor der Antwort Thach Van