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?


  • Mod

    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!


  • Mod

    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.


Anmelden zum Antworten