schlechte zufallsfahlen ?
-
In der boost sind noch spezielle Zufallszahlen-Libraries drin. Vielleicht helfen die.
-
hi,
danke für die Info, hab mir den Artikel mal durchgelesen, soweit verstanden und umgesetzt.meine Berechnung der Zufallszahlen sieht jetzt so aus:
int ignore = (RAND_MAX / 10000) * 10000; z = rand(); while ( z > ignore ) { z=rand(); } // zahl = (z%10000)+1; if (zahl <=5000) counter++;bei 8148576 Zufallszahlen sind 3566648 kleiner als 5000!
Also immer noch ~43% unter 5000.
@ chrische
Warum Trittbrettfahrer ?Danke
Chris
-
chri5 schrieb:
bei 8148576 Zufallszahlen sind 3566648 kleiner als 5000!
Also immer noch ~43% unter 5000.
Also das ist merkwürdig (ich hab' jetzt keine Lust auszurechnen, wie hoch die Signifikanz deines Tests ist) - könntest du die Verteilung noch ein wenig feiner aufdröseln? (und ändern sich die Werte möglicherweise, wenn du das Programm mehrfach durchlaufen lässt - mit unterschiedlichen Ausgangswerten für srand()?)
@ chrische
Warum Trittbrettfahrer ?Bei dem Namen fragst du noch ;)?
-
Also 10000 Stichproben sind bei einer Monte-Carlo-Simulation, insbesondere, wenn deutlich mehr mit releativ geringem Zeitaufwand möglich sind, schon wenig.
Außerdem würde ich eher ein Histogramm als Mittel zu Analyse nehmen. Weiterhin sind die Standardabweichung und das arithmetische Mittel interessant.
-
chri5 schrieb:
hallo,
ich generiere in C++ mit rand() zufallszahlen zwischen 1-100.Um mal zu testen wie gut die Zufallszahlen sind, zähle ich bei gewürfelten jeder zahl zwischen 1 und 50 einen counter hoch.
Dh bei 10000 zufallszahlen müsste der counter bei ca 5000 wenn die zufallszahlen gut sind oder ? ...
leider errecihe ich aber nur 4378, also kommen die zahlen 1-50 häufiger vor als die zahlen 51-100.
gibts da andere möglichkeiten , bessere Zufallszahlen zu würfen ?
Danke
chrisIrgendwas hast du falsch gemacht.
#include <stdlib.h> int main() { int counter = 0; for (int i = 10000; i; i--) { if ((rand()%100)+1 < 51) counter++; } // counter == 4975 ! return 0; }
-
hi,
mit dem folgenden Programm habe ich rand() mit einem von mir geschriebenen Zufallszahlengenerator (Lehmersche lineare Kongruenzmethode) getestet. Verwendet wurde gcc. Ergebnisse siehe unten.unsigned long lehmer(unsigned long s) // Lineare Kongruenzmethode nach Lehmer { static unsigned long a = 1, b = 4194301, c = 2147483647, z = b; z = (a + b * z) % c ; return z % s; } void test_lehmer() { long unsigned n = 100000, mp = RAND_MAX, iz1, od1=0, iz2, od2=0; double s1=0, ss1=0, zz1, mi1, va1, s2=0, ss2=0, zz2, mi2, va2; for (int i = 0; i < n; i++) { iz1 = lehmer(mp); iz2 = rand(); if ( iz1 % 2 ) od1 ++; if ( iz2 % 2 ) od2 ++; zz1 =((double)iz1 / ((double)(mp)+ 1 ) ); zz2 =((double)iz2 / ((double)(mp)+(double)(1)) ); s1 += zz1; ss1 +=zz1*zz1; s2 += zz2; ss2 +=zz2*zz2; } cout << "Ergebnisse fuer Randomgenerator Lehmer (Periode: " << mp << ")" << endl; mi1 = s1 / n; va1 = ((ss1 - n * mi1*mi1)/n); cout << "Anzahl n: " << n << ", davon ungerade: " << od1 << ", Summe: " << s1 << " E(Summe): " << n / 2 << endl; cout << "Mittelwert: " << mi1 << ", Varianz: " << va1 << ", E(Varianz): " << 1.0/12 << endl; cout << "\nErgebnisse fuer Randomgenerator rand() (max. Periode: " << mp << ")" << endl; mi2 = s2 / n; va2 = ((ss2 - n * mi2*mi2)/n); cout << "Anzahl n: " << n << ", davon ungerade: " << od2 << ", Summe: " << s2 << " E(Summe): " << n / 2 << endl; cout << "Mittelwert: " << mi2 << ", Varianz: " << va2 << ", E(Varianz): " << 1.0/12 << endl; wait_return(); /* Ergebnisse für 10000 Zufallszahlen ---------------------------------- Ergebnisse fuer Randomgenerator Lehmer (Periode: 32767) Anzahl n: 10000, davon ungerade: 5031, Summe: 5028.66 E(Summe): 5000 Mittelwert: 0.502866, Varianz: 0.084465, E(Varianz): 0.0833333 Ergebnisse fuer Randomgenerator rand() (max. Periode: 32767) Anzahl n: 10000, davon ungerade: 5035, Summe: 5037.71 E(Summe): 5000 Mittelwert: 0.503771, Varianz: 0.0834414, E(Varianz): 0.0833333 Ergebnisse für 100000 Zufallszahlen ----------------------------------- Ergebnisse fuer Randomgenerator Lehmer (Periode: 32767) Anzahl n: 100000, davon ungerade: 50097, Summe: 50046.9 E(Summe): 50000 Mittelwert: 0.500469, Varianz: 0.083549, E(Varianz): 0.0833333 Ergebnisse fuer Randomgenerator rand() (max. Periode: 32767) Anzahl n: 100000, davon ungerade: 50145, Summe: 50146.1 E(Summe): 50000 Mittelwert: 0.501461, Varianz: 0.0832408, E(Varianz): 0.0833333 Ergebnisse für 10000000 Zufallszahlen ------------------------------------- Ergebnisse fuer Randomgenerator Lehmer (Periode: 32767) Anzahl n: 10000000, davon ungerade: 4987790, Summe: 5.00193e+006 E(Summe): 5000000 Mittelwert: 0.500193, Varianz: 0.0834284, E(Varianz): 0.0833333 Ergebnisse fuer Randomgenerator rand() (max. Periode: 32767) Anzahl n: 10000000, davon ungerade: 5000153, Summe: 4.99948e+006 E(Summe): 5000000 Mittelwert: 0.499948, Varianz: 0.0833409, E(Varianz): 0.0833333 */ }Mittelwerte und Varianzen der beiden Generatoren stimmen für 100000 und 10000000 relativ gut überein. Bei rand() sind von 10000000 Zufallszahlen 4999480 kleiner als 5000000, also 49,9948 Prozent. Auch Mittelwert und Varianz entsprechen mit 0.499948 und 0.083333 praktisch den Erwartungswerten von 1/2 und 1/12.
Wenn du nur 43 % erreichst, scheint irgendwas bei deiner Berechnung nicht zu stimmen. Welchen Compiler, Prozessor benutzt du?
Anzumerken ist noch, das die Anzahl der in einem Experiment verwendeten Zufallszahlen wesentlich kleiner als die Periode sein soll. Bei rand() ist die Periode gleich RAND_MAX, also 32767. lehmer hat eine max. Periode von 2147483647 (der Grund, warum ich den mal schrieb). Bei den im letzten Beispiel gewürfelten 10 000 000 Zufallszahlen gibt es also bereits 10 000 000 / 32767 = 305 Wiederholungen der gewürfelten Zufalszahlenfolge. Das ist für physikalische Experimente und auch für Dinge wie gestreute Speicherung recht ungünstig. Man sollte da Generatoren mit wesentlich größeren Perioden verwenden (Bei lehmer wären es 10000000 / 2147483647 = 0,0046 Wiederholungen gewesen. Zum Vergleich mit rand() wurde lehmer jedoch auch auf die Periode RAND_MAX begrenzt.)viele Grüße von tesu (auf Nachtwache:)
-
Hallo chri5
ich hab mir mal dein Programm angeschaut. Da stimmt ja wirklich nichts, siehe unten!chri5 schrieb:
hi,
danke für die Info, hab mir den Artikel mal durchgelesen, soweit verstanden und umgesetzt.meine Berechnung der Zufallszahlen sieht jetzt so aus:
int ignore = (RAND_MAX / 10000) * 10000; z = rand(); while ( z > ignore ) { z=rand(); } // zahl = (z%10000)+1; if (zahl <=5000) counter++;bei 8148576 Zufallszahlen sind 3566648 kleiner als 5000!
Also immer noch ~43% unter 5000.
@ chrische
Warum Trittbrettfahrer ?Danke
ChrisWenn ich dein Programm bei mir laufen lasse, erhalte ich folgendes:
1. ignore hat den Wert 30000
2. Das z vor der Schleife hat den Wert 32650
3. In der Schleife wird z gleich 5272 gewürfelt, die Schleife also genau 1mal durchlaufen. Du würfelst also keine 8148576 Zufallszahlen.
4. zahl ist dann 5273
5. counter enthält den zufälligen Wert 1094795585 weil er nicht initalisiert ist (falls du doch init. hast, dann Entschuldigung).So gehts also nicht.
vg tesu
-
Nimm doch den http://www-personal.engin.umich.edu/~wagnerr/MersenneTwister.h
MfG
-
hi ceplusplus,
vielen Dank für diesen genialen Generator. Der schlägt rand() natürlich um Längen. Man muss ihn allerdings auch richtig anwenden, sprich programmieren können
Grüsse von Ney
-
das mein programm nicht so oft durchläuft ist mir schon klar, die while Schleife dient zu einem anderen Zweck!
CStoll hat mich auf einen Artikel im Magazin hingewiesen, vielleicht solltest die den auch mal durchlesen dann weist warum ich da ne while hab.
Kurz gesagt, am Beispiel:
zufallszahlengenerator 8 bit , also 0-255;
begrenze ich meine zufallszahlen mit modulo 200, kommen die zahlen 0-55 einmal öfter vor als die restliuchen deswegen wir bei zahlen > 201 nochmal gewürfelt.Das ganze ist nur ein Ausschnitt aus meinem Programm, natürlich wird der counter mit 0 initialisiert und natürlich is da noch irgendwo ne for-schleife die 8148576 durchlaufen wird.
Danke das dich so viel mit meinem Programm befasst hast.
chris