Warum gibt rand() % 7 immer 0 zurück?

Lesezeit: 3 Minuten

Benutzeravatar von 0xdead10cc
0xtot10cc

Dies scheint ein wirklich seltsames Problem zu sein:

Das ist mein Code:

#import <Foundation/Foundation.h>

int main (int argc, const char * argv[])
{
    @autoreleasepool {
        srand((unsigned int)time(NULL));
        int newRandomNumber = 0;
        newRandomNumber = rand() % 7;
        NSLog(@"%d", rand() % 7); //This prints out what I expected
        NSLog(@"newRandomNumber = %d", newRandomNumber); // This always prints out 0!
    }
    return 0;
}

Wenn ich diese eine Zeile ersetze, die besagt

newRandomNumber = rand() % 7

mit

newRandomNumber = rand() % 8

alles funktioniert einwandfrei. Warum ist das so?

  • Kann dein Problem in nicht reproduzieren C.

    – Matte

    23. Oktober 2011 um 14:42 Uhr

  • Ich kann dies in Objective-C reproduzieren. Sogar mit srand([[NSDate date] timeIntervalSince1970]). Aber Übergabe kleinerer Ganzzahlen an srand() scheint es zu beheben.

    – Lukman

    23. Oktober 2011 um 14:47 Uhr

  • Was erhalten Sie, wenn Sie rand() drucken? Erhalten Sie jedes Mal die gleiche Zahl oder nur etwas, das zu 0 modulo 7 kongruent ist?

    – Omri Barel

    23. Oktober 2011 um 14:48 Uhr

  • Hast du mehr als einmal versucht zu iterieren? Ich vermute, dass der erste Wert von rand() immer ein Vielfaches von 7 ist.

    – Heiße Licks

    17. November 2013 um 15:44 Uhr

  • verwandt: Rand() % 14 erzeugt nur die Werte 6 oder 13

    – phuklv

    7. August 2018 um 8:03 Uhr

Benutzeravatar von Georg
georg

Nun, das

int seed;
for(seed = 1; seed < 10; seed++) {
    srand(seed);
    printf("%4d %16d\n", seed, rand());
}

Drucke

   1            16807
   2            33614
   3            50421
   4            67228
   5            84035
   6           100842
   7           117649
   8           134456
   9           151263

was mich das denken lässt rand() = seed * 16807

Wikipedia-Artikel Linearer Kongruenzgenerator bestätigt, dass CarbonLib tatsächlich Xn+1 = Xn * 16807 verwendet, um Zufallszahlen zu generieren.

  • Formel unter Linux 2.6.32, die ich ausführe, ist komplizierter. Es hat die Form next = ( next * const_1 + const_2) % 32.768. Offensichtlich haben Sie die Formel Ihrer Plattform möglicherweise rückentwickelt. Es ist jedoch implementierungsabhängig mit Konstanten, die nach dem Drehen und Wenden oft nahezu Primzahlen sind.

    – Gnometorule

    23. Oktober 2011 um 18:12 Uhr

  • Es ist jedoch unwahrscheinlich, sie zuerst einfach zu Resten ohne andere Transformationen zu machen.

    – Gnometorule

    23. Oktober 2011 um 18:13 Uhr

  • Was für eine schlechte Wahl von LCG

    – phuklv

    18. April 2015 um 9:00 Uhr

  • Der Teil, den Sie ausgelassen haben: seit 16807 % 7 == 0, (n * 16807) % 7 == 0 auch, solange Sie keinen Integer-Überlauf bekommen haben.

    – Markieren Sie Lösegeld

    24. September 2015 um 18:49 Uhr

Benutzeravatar von Grady Player
Grady-Spieler

Es scheint unwahrscheinlich, aber bei einigen Tests scheint der erste Rand nach einem Srand immer durch 7 teilbar zu sein, zumindest in einer Variable mit Int-Größe.

Bei mehreren Läufen erhielt ich 1303562743, 2119476443 und 2120232758, die alle 7 auf 0 modden.

Der Zweite rand() funktioniert, weil es das zweite ist rand(). Werfen Sie einen rand() vor deinem ersten rand()… oder noch besser, verwenden Sie einen besseren Zufallszahlengenerator random oder arc4rand wenn verfügbar.

Siehe auch Stack Overflow-Frage Warum ist (rand() % irgendetwas) in C++ immer 0?.

  • Grady Player beantwortet Ihre Frage ziemlich genau: Dies liegt daran, dass es sich um Ihren ersten Anruf bei einer nicht wirklich zufällig generierten Nummer handelt. Aber noch ein Punkt und eine Tatsache, die mich immer noch verwirrt:

    – Gnometorule

    23. Oktober 2011 um 16:19 Uhr

  • (1) Wenn Sie mit stand() überhaupt nichts sehen, wird das System beim ersten Aufruf immer die vernünftige Nummer erzeugen. Auf meinem System verfolgt eine ‘next’-Variable den nächsten rand()-Wert, und next wird auf 1 gesetzt, wenn kein srand()-Aufruf erfolgt. Der zurückgemeldete Wert ist nach dem Addieren und Multiplizieren von Systemkonstanten und dem Ergebnis mod 32.768. Das bedeutet, dass Sie für einen bestimmten Modulus-Benutzer, der beim ersten Anruf ausgewählt wurde, immer noch 0 erhalten würden, in Ihrem Fall 7, aber es könnte eine andere Nummer sein.

    – Gnometorule

    23. Oktober 2011 um 16:23 Uhr

  • (2) Der Artikel spricht über Portabilitätsprobleme, die durch die Verwendung eines Moduls nicht beeinträchtigt würden. Im Wesentlichen weist es darauf hin, dass time_t möglicherweise nicht richtig in ein unsigned int umgewandelt werden kann; und dass es besser ist, mod nicht zu verwenden, sondern zu multiplizieren, um den gewünschten Bereich zu erhalten (in Ihrem Fall *7/RAND_MAX). Als dieses objektive C, das ich nicht kenne, könnte es ein Problem sein, aber ich bezweifle es. Was mich verwirrt, ist, dass der zurückgemeldete time()-Wert intern bei jedem globalen Timer-Interrupt in update_tines() (auf jeden Fall auf dem LINUX 2.6.xx-Kernel) aktualisiert wird, und dies sollte weit zwischen Sekunden-Ticks geschehen.

    – Gnometorule

    23. Oktober 2011 um 16:29 Uhr

  • Warum srand() zurückmelden würde, wie Sie es sagen, was im Wesentlichen 7-Sekunden-Schritte ausmacht (ich weiß, dass dies nicht genau das bedeutet, aber es scheint verwandt zu sein), lässt mich am Kopf kratzen.

    – Gnometorule

    23. Oktober 2011 um 16:30 Uhr

1394950cookie-checkWarum gibt rand() % 7 immer 0 zurück?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy