C++ Random Double zwischen zwei Werten?

Zeboo

Lt. Commander
Registriert
Juli 2008
Beiträge
1.562
Hallo. Bin etwas verpeilt.

Ich weiß wie ich ganze Randomzahlen zwischen zwei Zahlen herausfinden kann:
PHP:
random = (rand()%3)-1;

Das wäre jetzt -1,0 oder 1

Was ist wenn jetzt wirklich alles (als double) was zwischen -1 und 1 ist ausgeben will? Wie kriege ich die Random Kommazahlen? Doing*

Gruß
 
häng zwei oder drei (oder auch mehr) Nullen hinten dran und Teile es dann durch die Zehnerpotenz :)

So machs ichs immer xD Ist vielleicht nicht grad elegant, aber klappt wunderbar :)
 
Wie viel Stellen soll denn deine Komma-Zahl haben?

5 Stellen? Dann mach einfach eine RND 0 - 10000 und teile durch 10000 nachher
 
Hängt davon wieviel Kommastellen du brauchst.

rand liefert dir eine Zahl zwischen 0 und 32768 zurück
das kannst jetzt zb. % 20000 rechnen
damit hast du eine zahl zwischen 0 und 20000
dividieren durch 10000 (flieskomma division) und dann -1
damit hast du eine zahl zwischen -1 und 1 mit bis zu 4 Kommastellen
in Code
Code:
double result = ((double)(rand()%10000)/10000.0) -1.0; // bitte Klammen nachprüfen :-/

Falls du was aufwendigeres brauchst, musst du eine externe Library nehmen die dir "Echte" bzw. grössere Random Zahlen generiert.
z.b. http://libtom.org/?page=features&whatfile=crypt
 
double random(double min, double max) {

return min + std::rand()*(max - min) / RAND_MAX;
}
 
Ich würde dir empfehlen nicht den Pseudo-RNG aus der C-Bibliothek zu verwenden (rand()), sondern einen anderen z.B. aus OpenSSL oder Crypto++.
Das Problem bei rand() ist nämlich, dass der Zahlenraum dort sehr klein ist (sehr viel kleiner als die Genauigkeit eines double-Wertes).
 
IceMatrix:

Würde noch ergänzen, dass mit "rand()%x" nicht jedes Ergebnis gleich wahrscheinlich ist.
Wenn rand() Werte von 0 bis n ausgibt, treten die Werte von 0 bis n%x häufiger auf als
der Rest.
 
Modulo gibt maximal Divisor-1 zurück.
Das heißt, bei Modulo kommen die ganze Zahlen von 0 bis x-1 raus.
http://de.wikipedia.org/wiki/Division_mit_Rest#Nat.C3.BCrliche_Zahlen
Diese Schreibweise für den Wertebereich ist dir vielleicht nicht ganz geläufig ("von inklusive Null bis nach exklusive x"->[0,x) )
Deine Formel ergibt immer nur was kleineres als x, per Definition, oder du bist der erste, der "int operator%(const int&)" überladen hat.

BTT:
Als Bibliothek hätte ich noch <wincrypt.h>. Geht halt nur unter Windows. Sonst kann man auch mit rand die Zahlen "präziser" oder "zufälliger" machen, in dem man rand() öfters aufruft (und irgendwann mal srand() ausführt).
 
Ich weiß schon, was [0,x) bedeutet, aber mir ging es um etwas ganz anderes.

Wenn ich beispielsweise eine Funktion namens rand() habe, die gleichverteilte unabhängige und echte
Zufallszahlen allerhöchster Güte im Bereich von 0-2 ausspucken würde, und ich wollte aber nur 0 oder 1
haben, und das versuche mit rand()%2 zu bekommen, kommt die 0 doppelt so häufig raus wie die 1.

0 % 2 = 0
1 % 2 = 1
2 % 2 = 0

RAND_MAX ist in der Regel natürlich größer, aber der Effekt ist immer der selbe. Deshalb ist es eine
schlechte Idee, die Zufallszahlen auf diese Weise auf eine kleinere Menge zu reduzieren.

€dit:
Eine Funktion, die diesen Effekt vermeidet, habe ich mal für ein Projekt von mir geschrieben:
http://devotchka.vellocet.net/boskop/browser/trunk/src/rrand.c?rev=171

die Seedfunktion srrand() nimmt einen seedwert für srand() und einen FILE-Zeiger, aus dem
Zufallszahlen gelesen werden können (z.B. /dev/random). Letzterer wird bevorzugt. Nur wenn
der Zeiger NULL ist, wird auf rand() als Zufallsquelle zurückgefallen.

rrand() nimmt als Parameter die Obere Schranke - 1 des Intervalls, aus dem die Zufallszahlen
kommen sollen. Untere Schranke ist 0.

Wenn die Zufallszahlenquelle gleichverteilt ist, ist das Ergebnis von rrand() garantiert auch
gleichverteilt. Im Gegensatz zu dem Modulo-Gemurkse.
 
Zuletzt bearbeitet:
lol, du bist gut:
Sagen wir, wir könnten eine Funktion definieren:
f(x)=x%2
Dann wäre der Mittelwert doch die Wahrscheinlichkeitsverteilung:
MW = fnInt(f(x),X,0,n)/n
So alteriert die Funktion immer regelmäßig zwischen 0 und 1 wodurch für n->unendlich der Mittelwert gegen 0.5 strebt.

Oder eine einfache Erklärung: rand() liefert mit RAND_MAX=65535 16 zufällige Bits. Wenn diese wirklich zufällig sind, dann ist die Wahrscheinlichkeit, dass das LSb 0 oder 1 ist, jeweils 50% und damit ist es ein guter/gerechter Zufallsgenerator. (Bei mir ist RAND_MAX 0x7fff und damit ist es eine gerade Menge an Zufallszahlen und damit ist bei meiner Plattform die Gleichverteilung für %2 gewährleistet.)

Wenn du sagst, dass es eine schlechte Idee ist, wie würdest du dann eine Zufallszahl auf die kleinste Information reduzieren? "Random.next()&1"?

Dabei berücksichtigen wir beide ja nicht, dass gerade rand() höchst ungleichmäßige Verteilungen der Zufallszahlen aufweist (je nach Implementierung).
Allerdings ist gerade OpenSSL ein Beispiel dafür, wie man Zufallszahlen schlecht generieren kann.
http://de.wikipedia.org/wiki/Hypertext_Transfer_Protocol_Secure#Verschl.C3.BCsselung
 
Das war ein Beispiel für Werte von 0,1 und 2. Wenn dein RAND_MAX 65535 ist, tritt der Effekt beispielsweise
bei rand()%10 auf, so dass 0-5 häufiger auftreten werden als 6-9.
Denn jeder Wert von 0-9 tritt im Bereich von 0-65529 jeweils 6553 mal auf, während die Werte 6-9 im Bereich
von 65530-65535 modulo 10 nicht mehr auftreten können.

0-5 werden also jeweils im Durchschnitt mit der Wahrscheinlichkeit 6554/65536 auftreten
6-9 jedoch nur mit der Wahrscheinlichkeit 6553/65536
Und wie man sofort sieht, ist das nicht mehr 10% für alle Möglichkeiten.

Rechne es halt aus: (6 * 6554 + 4 * 6553) / 65536 = 1

Es sind also nicht mehr alle Werte im Bereich von 0 bis 9 gleich wahrscheinlich, selbst wenn die Ausgabe
der Zufallsfunktion gleichverteilt ist.

Allgemein tritt das Problem immer auf, wenn der rechte Operand der Modulo-Operation kein Teiler von
RAND_MAX + 1 ist.
 
Zuletzt bearbeitet:
Hi. Danke für die Tips. Eig. habe ich jetzt mehr als genug Auswahl ;)
 
Blitzmerker schrieb:
Schon klar, aber was wäre dein Lösungsansatz dafür?

Ausgehend vom nicht gleivchverteilten rand()%x:
Wirf die "oberen" paar Fälle von rand(), die für die Ungleichverteilung sorgen, einfach weg. Also

rand() würfeln
testen, ob rand() > RAND_MAX - (RAND_MAX+1)%x
nein ==> rand() verwenden, ja ==> nochmal von vorn
 
Zuletzt bearbeitet:
Zurück
Oben