Rechteckverteilung bei Zufallszahlen
-
Hey allerseits,
ich benötige einen Zufallsgenerator, der nicht wie rand ungleichmäßig zufallszahlen ausspuckt, sondern eine Rechteckverteilung. Sprich jede Zufallszahl hat die gleiche Chance ausgespuckt zu werden.
Mit dem Zufallsgenerator sollen Koordinaten in x, so wie y Richtung von -100 bis +100 entstehen.
....
int x_k, y_k;srand(time(NULL)
x_k=rand()%101;
x_k=(rand()%2==0)?x_k:-x_k;
......Verteilung bei Rand sieht ungefähr so aus: 0 bis rand_max/2 > 50%
und rand_max/2 bis rand_max demensprechend weniger.Vllt kann mir jemand helfen. fände ich super!
Cheers
-
Hans-Stein schrieb:
Verteilung bei Rand sieht ungefähr so aus: 0 bis rand_max/2 > 50% und rand_max/2 bis rand_max demensprechend weniger.
Wo und wie hast du das festgestellt?
-
rand() erzeugt gleichverteilte Zufallszahlen. Deine Messung ist falsch.
-
Also draufgekommen bin ich, nachdem ich bei meinem statistisch ermittelten wert pi kein exaktes ergebnis bekommen habe.
Einfach mit hilfe von einer if-abfrage und jedes mal, wenn der wert kleiner 50 ist bei einem vorher definierten Zähler zum Beispiel int i = 0; einen Wert dazuzählen sprich i++; und dann schaust du dir die anzahl an, die kleiner 50 sind und der rest ist dann über 50. wenn du jetzt 10 zufallszahlen machst ist das prozentual sehr gering, aber bei 10^6 zahlen eben nicht mehr.
-
@ seppj:
scheinbar nein! sonst würde bei der prozentuale fehler bei der zahl pi bei 10^5 - 10^6 nicht größer als ein promill sein.
der fehler kann nur an einer nicht linearen verteilung der zufallszhalen liegen!
-
Der Fehler liegt 100% bei dir, das kann ich dir garantieren.
Dass bei statistischen Verfahren dennoch nichts gutes rauskommt, kann übrigens auch andere Gründe haben. Die rand() Zufallszahlen sind z.B. oftmals nicht besonders gut, was ihre Korrellationen angeht. Aber gleichverteilt sind sie garantiert.
Wie kommst du auf die Fehlerabschätzung zur Bestimmung von Pi? Die statistische Bestimmung von Pi konvergiert grauenhaft langsam. Ein Fehler im Promillebereich kommt mir wahnsinnig gut vor für 10^6 Stichproben. Habe es jetzt nicht nachgerechnet, aber das klingt falsch.
-
Zeig mal Dein Programm. Deine Beschreibung ist zu unpräzise, da fallen mir gleich mehrere Fehler ein, die zu Deinen Beobachtungen passen.
-
Also ich bin mir ziemlich sicher, dass die Berechnung stimmt. Der Zufallsgenerator wird durch srand initialisiert und startet somit immer bei einem anderem Wert. Wie erklärst du dir sonst, dass rand() mir mehr kleine als große Zahlen liefert. Was wäre die Lösung des Problems, um die Korrelation besser zu machen?
-
Also ich kann leider nur einen Teil von meinem Programm einstellen. Die Aufgabe ist grafisch zu lösen, deswegen lasst euch von den unterprogrammen greendots(hwndMain) nicht stören:
BOOL punkte (HWND hwnd)
{
extern int x_k, y_k; //Koordinaten
double z_k; //Fallunterscheidung
double wurzel; //Quadratzwurzel
int zaehler = 0; //Zaehlt die Anzahl
extern int anzahl; //Eingelesene Versuchsanzahl
extern int in; //Anzahl der Punkte im Kreis
in = 0;
extern int out; //Anzahl der Punkte außerhalb des Kreis
out = 0;
int x = 0;
int y = 0;
extern int aus; //Schalter für Animation
extern HWND hwndMain; //Für Programmaufruf von reddots/greendots(hwndMain)
extern int schalter; //Schalter für WM_Paint
extern double gr;
extern double gr2;
printf("\n\nAusknopf: %i", aus);srand(time(NULL));
while(anzahl+1 >= zaehler)
{
zaehler++;//X-Koord. würfeln
x_k = rand()%101;
x_k = ((rand()%2)==0)?x_k:-x_k;
my_random_double();//Y-Koord. würfeln
y_k = rand()%101;
y_k = ((rand()%2)==0)?y_k:-y_k;//printf("\n\n %i\n %i", x_k, y_k);
wurzel = sqrt((double)x_k*(double)x_k + (double)y_k*(double)y_k);
if(wurzel == 100)
{
z_k = rand()%2;wurzel = wurzel - z_k;
printf("\n\nWurzel: %lf", wurzel);
}//Fallunterscheidung
if (wurzel < 100)
{
in++;
if(aus != 1)
{
greendots(hwndMain);
}
}
else
{
out++;
if(aus != 1)
{
reddots(hwndMain);
}
}}
schalter = 0;berechnung(hwnd);
return 0;
}
-
Wo kommt es bei dem Programm denn auf die Verteilung Kleiner/größer RAND_MAX/2 an?
Versuch mal x_k = (rand()%201)-100; (bei y_k auch)
Und srand(time(NULL)); gehört an den Anfang der main()
-
Mach bitte CODE-Klammern um den Code.
Mit Modulo machst du übrigens leicht die Verteilung kaputt.
-
main() ist in einer .c Datei. Das ist ein Ausschnitt meiner Unterprogramme.c datei. Da sind nur Unterprogramm enthalten. Deswegen denke ich ist srand dort ganz gut aufgehoben?
Mein ganzes Programm wäre zu lang um es hier reinzukopieren. Vor allem, weil es mehrere Dateien sind.das mit rand_max war in einem Versuchsprogramm, der meine Vermutung bestätigt hat.
Hilft übrigens nichts! Aber danke für die Antwort
-
Sorry was sind Codeklammern?
-
Dieses Programm bestätigt deine Vermutung nicht:
#include <stdlib.h> #include <stdio.h> #include <time.h> #define ANZ 5000000 #define ANZ2 100 int main() { long i,j,l=0,k=0; srand ( time(NULL) ); for(j=0;j<ANZ2 ;j++) { for(i=0,l=0;i<=ANZ ;i++) { if (rand()< (RAND_MAX/2)) l--; else l++; } printf("%ld\n", l); k+=l; } puts("-------"); printf("%ld\n", k); return 0; }
Zumindest bei mir.
Und srand sollte nur einmal im Programm aufgerufen werden.
Codeklammern kriegst du mit dem C/C++ Button unter den
und das sieht dann wie oben aus.
-
Hmmm komisch. Also ich habe es heute Mittag mit meinem Prof ausprobiert gehabt. Und da sah es nicht so schön aus. Bei deinem sieht es echt sher ausgeglichen aus!
Also rand kann ja nicht einmal so und einmal so funktionieren
-
Mein Testprogramm:
#include <stdio.h> int r[201]; int main() { int x; srand(time(NULL)); int i; for (i = 0; i < 1000 * 1000; i++) { x = rand() % 101; x = (rand() % 2 == 0) ? x : -x; r[x + 100]++; } for (i = 0; i < 201; i++) printf("%d:\t%d\n", i - 100, r[i]); return 0; }
Ergebnis:
-100: 4871 -99: 4944 -98: 4833 -97: 4909 -96: 4999 -95: 4870 -94: 4989 -93: 4853 -92: 4881 -91: 4808 -90: 4979 -89: 5037 -88: 4901 -87: 5045 -86: 5112 -85: 4951 -84: 4820 -83: 4917 -82: 4910 -81: 4947 -80: 4979 -79: 4890 -78: 4993 -77: 4966 -76: 4878 -75: 4925 -74: 4995 -73: 4916 -72: 4940 -71: 5105 -70: 5060 -69: 4887 -68: 4881 -67: 4934 -66: 4916 -65: 4993 -64: 4891 -63: 4948 -62: 4983 -61: 5198 -60: 4793 -59: 4968 -58: 4930 -57: 4906 -56: 4887 -55: 4880 -54: 5023 -53: 5043 -52: 5041 -51: 4945 -50: 4957 -49: 5000 -48: 5022 -47: 5003 -46: 4925 -45: 4860 -44: 5029 -43: 4935 -42: 5051 -41: 4940 -40: 4992 -39: 5025 -38: 4786 -37: 4848 -36: 4894 -35: 5041 -34: 4927 -33: 5028 -32: 5057 -31: 5042 -30: 4916 -29: 5006 -28: 4903 -27: 4971 -26: 4965 -25: 4919 -24: 4966 -23: 4983 -22: 4924 -21: 4951 -20: 4902 -19: 4906 -18: 5029 -17: 5055 -16: 5007 -15: 4988 -14: 4944 -13: 4930 -12: 5036 -11: 4944 -10: 4958 -9: 4838 -8: 4859 -7: 5007 -6: 4944 -5: 5064 -4: 5024 -3: 4955 -2: 4878 -1: 4861 0: 9837 1: 4995 2: 4906 3: 4942 4: 5008 5: 4950 6: 4907 7: 4934 8: 4929 9: 4885 10: 4983 11: 4910 12: 4871 13: 5084 14: 4838 15: 4856 16: 4983 17: 5030 18: 4898 19: 4921 20: 4834 21: 4996 22: 4998 23: 4910 24: 5026 25: 5013 26: 5026 27: 4889 28: 4968 29: 4963 30: 5009 31: 4880 32: 4894 33: 5058 34: 5045 35: 4941 36: 5037 37: 4871 38: 5080 39: 4891 40: 4978 41: 4821 42: 4918 43: 5001 44: 5018 45: 4914 46: 4981 47: 4813 48: 4974 49: 5006 50: 5007 51: 4935 52: 4921 53: 4973 54: 4962 55: 4866 56: 4925 57: 4999 58: 5044 59: 4996 60: 4927 61: 4979 62: 5038 63: 4968 64: 4939 65: 4952 66: 4948 67: 4930 68: 4860 69: 4884 70: 5041 71: 4986 72: 5119 73: 4950 74: 4948 75: 4921 76: 4913 77: 4955 78: 5011 79: 4906 80: 5017 81: 5008 82: 4916 83: 4994 84: 5057 85: 4882 86: 4884 87: 4810 88: 5011 89: 4862 90: 4992 91: 4877 92: 4907 93: 4971 94: 4934 95: 4944 96: 4809 97: 4865 98: 4930 99: 4938 100: 4904
Sieht doch super aus. Nur die 0 ist doppelt.
-
earli schrieb:
Nur die 0 ist doppelt.
Dann mach statt
x = rand() % 101; x = (rand() % 2 == 0) ? x : -x;
x_k = (rand()%201)-100
und die doppelte 0 ist auch weg.
-
DirkB schrieb:
earli schrieb:
Nur die 0 ist doppelt.
Dann mach statt
x = rand() % 101; x = (rand() % 2 == 0) ? x : -x;
x_k = (rand()%201)-100
und die doppelte 0 ist auch weg.
Ich hab das ja genau vom Fragesteller übernommen.
-
Also die Null darf ruhig doppelt vorkommen. Macht ja nichts!
[cpp]
#include <stdio.h> #include <time.h> #include <stdlib.h> int main(void) { int zz; long anzahl = 10000000; int i = 0; int kleiner=0; int groesser=0; srand ( time(NULL) ); while(i <= anzahl) { zz = rand()%101; if(zz <= 50) { kleiner++; } else { groesser++; } i++; } printf("\n\nkleiner:%i\n\ngroesser:%i", kleiner, groesser); return 0; }
-
Du hast mit rand()%101; auch 101 Werte (0 bis 100)
Von 00 bis 050 hast du 51 Werte und
von 51 bis 100 hast du 50 Werte.Kalr dass das Ungleich verteilt ist.