randomize() spinnt!

  • Ich versuche gerade einen Würfelwurf zu implementieren mit einem 6-seitigen Würfel. Dazu müsste ich doch zuerst randomize() verwenden, damit rand() eine Zufallszahl liefert. Das komische ist jetzt, das die ausgabe von

    cout << (rand()%6 + 1);

    bei mir zuerst einpaar mal eine 1 liefert, dann einpaar mal eine 2, dann paar 3er, 4er, 5er und dann ein paar 6er. Die genaue Anzahl ist immer unterschiedlich, aber immer in dieser Reihenfolge!

    Weiß jemand, was ich falsch mache?

    Ich hab auch den kleinen Quellcode und das kompilierte Programm upgeloaded, würd mich freuen, wenn sich jemand kurz die Zeit nimmt, es bei sich am PC zu testen, vielleicht liegts auch an meinem Rechner (kann mir sonst nichts vorstellen...)

    '100 little bugs in the code, 100 bugs in the code. Fix one bug, compile it again: 101 little bugs in the code.
    101 little bugs in the code . . .'
    Continue until 0 Bugs reached...

  • in c++ liefert rand() einen Wert zwischen 0 und 32767 (siehe weiter unten)

    Ich habs inzwischen mit random(6) versucht, da schauts aber auch nicht viel besser aus: die Zahlen sind nachher schon zufällig, doch kommt für eine gewisse Zeitspanne immer die gleiche Zahl, auch wenn man randomize() verwendet.

    In der Library hab ich dann die Definitioni von random(int) und rand() gefunden:

    inline int _RTLENTRY random(int __num)
    { return __num ? (int)(_lrand()%(__num)) : 0; }

    /* Maximum value returned by "rand" function */
    #define RAND_MAX 0x7FFFU

    inline void _RTLENTRY randomize(void) { srand((unsigned) time(NULL)); }

    Mich wundert, dass in der Definition von randomize ein time-Objekt übergeben wird. NULL ahnung, wieso...

    '100 little bugs in the code, 100 bugs in the code. Fix one bug, compile it again: 101 little bugs in the code.
    101 little bugs in the code . . .'
    Continue until 0 Bugs reached...

  • hi

    also das time-Objekt ist meines wissens dafür verantwortlich, daß die generierte zahl wirklich zufällig ist.
    Würde man immer den gleichen Startwert für nen randomizer verwenden, würde man immer die gleiche zahlenfolge erzeugen.

    i hoff das stimmt so :)

    mfg
    Roli

    Sex (female) is: grep; touch; unzip; touch; gasp; finger; gasp; mount; fsck; more; yes; gasp; umount; make clean; make mrproper

    Sex (male) is: grep; touch; strip; unzip; head; mount /dev/girl -t wet; fsck; fsck; yes; yes; yes; umount /dev/girl; zip; sleep or good

  • ok, sorry hab gedacht das funktioniert so wie bei Java und Basic. Also auf der Seite ist ein Sample zum verwenden des rand():
    http://home1.gte.net/deleyd/random/crandom.html
    Kurz gesagt nimm einfach (double)rand()/(double)(RAND_MAX+1) um eine Zahl zw 0 und 1 zu erhalten. mit srand(seed) kann man den random number generator ein anderen seed zuweisen (seed vom Typ int). Da hilft sicher die System zeit (die Sache mit den Sekunden seit dem 1.1.1970) etwas herumtransformiert.

    p.s. es wird auf der Seite auch extra darauf hingewiesen das man nicht deine Methode verwenden soll:

    Zitat


    Note: Do NOT use

    y = rand() % M;

    as this focuses on the lower bits of rand(). For linear congruential random number generators, which rand() often is, the lower bytes are much less random than the higher bytes. In fact the lowest bit cycles between 0 and 1. Thus rand() cycles between even and odd (try it out). Be sure to do as above instead.


    mfg Zentor

  • martin: Auf der Seite steht nur das, was das randomize() selber macht, hilft mir nicht viel, danke.

    Roli: ist mir schon klar, nur frag ich mich, wiese gerade ein Time-Objekt übergeben wird (vor allem wenn wenn der Output immer für eine Zeitspanne der gleiche ist)

    Zentor: Danke, hat auch nix genutzt, Ausgabe trotzdem genauso wie von (rand() % Zahl + 1).


    Nochmal das Problem: Mein Programm hat immer folgende Ausgabe:

    Code
    for (unsigned int i = 0; i < 1000; i++)
        cout << rand()%6+1 << " ";

    2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 und noch uur viele 2er .... 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 dann verdammt viele 5er noch 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 usw...

    '100 little bugs in the code, 100 bugs in the code. Fix one bug, compile it again: 101 little bugs in the code.
    101 little bugs in the code . . .'
    Continue until 0 Bugs reached...

  • Bis jetzt hab ich die "zufälligste" Ausgabe mit random(6)+1 erhalten, aber da wechselt die Zahl, die ausgegeben wird auch nur (ca.) sekündlich.

    Wie schauts denn bei den Leuten aus, die das zip runtergeladen haben? Da niemand was dazu gepostet hat, geh ich mal davon aus, dass es bei denen nicht anders war.

    Soweit ich das sehe, erstellt srand(Zahl) die Zufallszahlen, randomize() ist srand(time(NULL)) und man muss immer warten, bis time(NULL) etwas anderes zurückgibt, wenn man mehrere Zufallszahlen will.

    Vielleicht gibt es eine Möglichkeit, srand mit Tausendstelsekunden zu füttern? Das wäre sehr angenehm...

    '100 little bugs in the code, 100 bugs in the code. Fix one bug, compile it again: 101 little bugs in the code.
    101 little bugs in the code . . .'
    Continue until 0 Bugs reached...

  • Nochmal ich:

    Hab das Problem folgendermaßen gelöst:

    clock(): Return number of clock ticks since process start.

    Ausgabe hatte aber immer noch zuviele wiederholungen, also hab ich immer etwas verzögert:

    Code
    for (unsigned short i = 0; i < 100000; i++)
    {
        srand(clock());
        treturn = _lrand() % dice + 1;
        clock_t endwait = clock() + 0.1*CLK_TCK;
        while(clock() < endwait);
        cout << treturn << " ";
    }

    Liefert endlich *wirklich* zufällige Zahlen, zwar nur 6-8 pro Sekunde, aber das genügt, glaub ich.

    '100 little bugs in the code, 100 bugs in the code. Fix one bug, compile it again: 101 little bugs in the code.
    101 little bugs in the code . . .'
    Continue until 0 Bugs reached...

  • du kannst alternativ zu

    #include < stdlib.h >

    srand(_irgendein_zufälliges_argument_);
    wuerfel = rand()%6;

    auch einfach aus /dev/random oder /dev/urandom lesen, wenn du unter Linux programmierst. Aber welchem Kernel das zur Verfügung steht bzw. obs andere Unices auch anbieten, weiß ich nicht genau, aber /dev/urandom liefert deutlich mehr (vorzeichenlose) Zufallszahlen als 6-8 pro Sekunde...

    aber wenn du als Argument für srand() was komplexeres wie ((time()%getpid())*getppid()) verwendest, solltest du eigentlich auch "echte" Zufallszahlen kriegen...

  • Ich programmier grad in dos, aber der Obige Ausdruck hat mich auf eine andere Idee gebracht (der Ausdruck selber hat leider nicht viel geholfen, da ja der Wert des Ausdrucks ((time()%getpid())*getppid() nur von time() abhängt)

    Code
    for (unsigned int i = 0; i < 10000000; i++)
    {
        srand(clock() * i * i);
        cout << random(6) + 1 << " ";
    }

    Frag mich, wieso ich nicht gleich drafgekommen bin??!?

    '100 little bugs in the code, 100 bugs in the code. Fix one bug, compile it again: 101 little bugs in the code.
    101 little bugs in the code . . .'
    Continue until 0 Bugs reached...

  • wenn du unter windows programmierst ist das einfachste:

    srand(GetTickCount());
    for(int i=0; i<1000; i++)
    {
    /*kann sein dass hier ein kleines argument fehlt, hab es selbst nicht kompiliert*/
    rand()%6+1;
    }


    das wichtige ist eigentlich srand(GetTickCount()); das du aber soweit ich weiß nur einmal ausführen musst, und nicht in jedem schleifenaufruf, hatte damit noch nie probleme

  • Das ist geil!! Wenn ich winbase.h include kommt folgende Compilermeldung:


    '100 little bugs in the code, 100 bugs in the code. Fix one bug, compile it again: 101 little bugs in the code.
    101 little bugs in the code . . .'
    Continue until 0 Bugs reached...

  • muss man eigentlich die winbase.h direkt includen?
    also wenn ich windows anwendungen schreibe, reicht normalerweise < windows.h> aus, der header included dann soweit ich weiß eh selbstständig winbase.h.

    es kann aber auch sein dass ich mich irre....

  • Zitat

    Original geschrieben von Soulmerge
    Ich programmier grad in dos, aber der Obige Ausdruck hat mich auf eine andere Idee gebracht (der Ausdruck selber hat leider nicht viel geholfen, da ja der Wert des Ausdrucks ((time()%getpid())*getppid() nur von time() abhängt)

    Ok, unter DOS hast du weder die /dev/ Devices, noch Pids...
    Aber in meinem Ausdruck hängt der Wert nicht nur von der momentanen Zeit, sondern auch von der Process ID deines Programmes, sowie von der PID dessen Vater-Prozesses... solche Ausdrücke kommen in vielen GNU Programmen als "random seed" vor...

    Btw, ich verstehe deinen code nicht ganz, eigentlich solltest du mit srand(long seed) den Zufallszahlengenerator initialisieren können, sofern "seed" eine "relativ zufällige" Zahl ist, und ab dann solle rand() vorzeichenlose Integerwerte von 0 bis RAND_MAX ausspucken, jedensfalls brauchst du srand() nicht in jedem Schleifendurchgang erneut aufrufen, bringt genau "void" :)

  • AAAAAAAARRRRGH!!!

    Wie kann man nur so einen blöden Fehler machen??????!?

    Nicht nur, das srand() in jedem Schleifendurchlauf nichts bringt, sondern es bringt mich genau auf den Fehler, durch den ich diesen Thread eröffnet habe! srand() initialisiert eine Folge von Zufallszahlen, nicht nur eine!

    *ärger*

    Vielen dank für den Hinweis!

    PS: getpid() gibt Prozess-ID zurück...

    '100 little bugs in the code, 100 bugs in the code. Fix one bug, compile it again: 101 little bugs in the code.
    101 little bugs in the code . . .'
    Continue until 0 Bugs reached...

  • Die Sache ist folgende: Bei einem Zufallsgenerator wird irgendeine beliebige Zahl als Startwert genommen. Bei jedem rand() wird der aktuelle Inhalt dieser Variable ausgegeben. Dann werden bestimmte Bits über irgendeinen Algorithmus miteinander verknüpft und an bestimmten Stellen in der Variable eingefügt, was einen (mehr oder weniger) zufälligen Folgewert ergibt.

    Mit randomize() wird einfach dieser Startwert gesetzt, was bei einer time-Variable mit der aktuellen Systemzeit auch "zufällig" ist. Wenn man randomize() aber mehrmals pro Sekunde aufruft, wird der Zufallsgenerator immer mit der gleichen Zahl initialisiert sodaß das darauffolgende rand() innerhalb einer Sekunde immer den gleichen Wert liefert.

    Lösung: randomize() nur ein mal aufrufen...

    EDIT: Die Variable, die den aktuellen Zufallswert und damit die Berechnungsgrundlage für den Folgewert speichert, nennt man auch "random seed" (vielleicht weil daraus der Folgewert "wächst"?)

    "The letters are Hex, of an ancient mode, but the language is that of Microsoft, which I shall not utter here."

  • Hier noch die Standardantwort aus comp.lang.c zu diesem Thema ...

    http://www.eskimo.com/~scs/C-faq/q13.16.html

    [EDIT]:
    Für jeden nichttrivialen Anwendungsfall empfehle ich zur Generierung von Zufallszahlen, entweder, einen eigenen Generator zu schreiben, oder zumindest jenen aus der BOOST Bibliothek zu verwenden.

    http://www.boost.org/libs/random/index.html

    Die meisten Implementierungen von srand(), rand() und co. sind nämlich meistens miserabel.

    Eins Zwei Gras Bär Hund Vier Muh Macht Die Kuh

  • moin!
    also zum thema random habe ich eine frage zum folgenen code:


    #include <iostream>
    #include <vector>
    #include <algorithm>
    #include <iterator>

    // for the random number generator
    #include <cstdlib>
    #include <ctime>

    using namespace std;

    class RandomNumber {
    public:
    RandomNumber() {
    srand(time(0));
    }

    int operator() ( int n) {
    return (int)((double)n * rand()/(RAND_MAX+1.0));
    }
    };

    int
    main(int argc, char **argv)
    {
    vector<int> v;
    v.push_back(1);
    v.push_back(2);
    v.push_back(3);
    v.push_back(4);
    v.push_back(5);
    v.push_back(6);
    v.push_back(7);
    v.push_back(8);
    cout<<v[0]<<v[1]<<v[2]<<v[3]<<v[4]<<v[5]<<v[6]<<v[7]<<v[8]<<endl;
    RandomNumber r;
    random_shuffle(v.begin(), v.end(), r);
    // copy(v.begin(), v.end(), ostream_iterator<int>(cout, " "));
    cout<<v[0]<<v[1]<<v[2]<<v[3]<<v[4]<<v[5]<<v[6]<<v[7]<<v[8]<<endl;
    return 0;
    }


    der code soll einen bitstring liefern. allerdings kommt staendig eine fehelrmedlung - weiss jemand woran das liegt?

    lg

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!