2010-11-24 6 views

Antwort

6

Wenn dies in C geschrieben ist, dann sind Sie ziemlich nah dran. Kompilieren Sie diesen Code:

#include <stdio.h> 
#include <stdlib.h> 

int main() { 
    int i; 
    for (i = 0; i < 1000000; i++) { 
     printf("%d\n", rand()%(35-18+1)+18); 
    } 
} 

Und es in einer Pipeline ausgeführt wird erzeugt diese Ausgabe:

[email protected]:~$ gcc -o test test.c 
[email protected]:~$ ./test | sort | uniq -c 
    55470 18 
    55334 19 
    55663 20 
    55463 21 
    55818 22 
    55564 23 
    55322 24 
    55886 25 
    55947 26 
    55554 27 
    55342 28 
    55526 29 
    55719 30 
    55435 31 
    55669 32 
    55818 33 
    55205 34 
    55265 35 

Der Schlüssel ist, dass Sie 1 hinzufügen vergessen - the fencepost error.

Sie können diese in eine Funktion verallgemeinern:

int random_between(int min, int max) { 
    return rand() % (max - min + 1) + min; 
} 
+4

Diese Technik führt eine Verteilung vor, wo die Divisor ist kein gerades Vielfaches von MAX_RAND. – NealB

+0

@NealB: Ja, ich dachte daran, das zu erwähnen. Die Fehlerbehebung ist jedoch nicht trivial, und für Testdaten, bei denen eine perfekte Verteilung keine große Rolle spielt, lohnt es sich nicht. – cdhowie

+0

Die Lösung ist ziemlich trivial, siehe meine Antwort ... – NealB

-1

nehmen rand() geben Sie eine Zahl zwischen 0 und 1,0

dann mit rand() * (35 - 18) + 18 eine Zufallszahl zwischen 18 und 35

bearbeiten zu bekommen: Sie brauche keine Mod dafür.

+1

'rand()' in C gibt 'int' zurück, was kein Fließkommatyp ist. Die Dokumentation für 'rand()' gibt an, dass es eine ganze Zahl zwischen 0 und "RAND_MAX" (einschließlich) zurückgibt. – cdhowie

+2

-1 falsche Annahme –

+0

? Wer hat Ihnen gesagt, dass es C. war? Java Math.random() gibt eine Zufallszahl zwischen 0 und 1. –

0
  1. Haben Sie Zahlen-only wollen?
  2. Möchten Sie eine gleichmäßige Verteilung?
  3. Möchten Sie sowohl 18 als auch 35 als mögliche Werte angeben?
  4. Welche Sprache möchten Sie verwenden?

in der Regel, wenn rand() gibt einen Float-Wert in [0,0 ... 1,0) (das heißt, Sie können Werte beliebig nahe an 1,0 erhalten, aber nicht wirklich 1) dann werden Sie wollen etwas wie

hi = 36 
lo = 18 
res = int((hi-lo)*rand() + lo) # returns random values in 18..35 

Hinweis, dass dies nie wirklich den hallo Wert zurück - deshalb habe ich es um 1 erhöht (dh, werden Sie alle Werte von 18 bis 35 einschließlich, aber nie 36).

Hoffe, dass hilft.

12

Abhängig von der Sprache, die Sie verwenden, kann der eingebaute Zufallszahlengenerator bereits diese Fähigkeit haben - machen Sie ein bisschen mehr Forschung.

Angenommen, der Zufallszahlengenerator, den Sie immer zurückgegeben haben Zahlen in einem bestimmten Bereich. Nur um des Arguments willen sagen wir, der Bereich ist 0..65536 aber Sie wollen Zufallszahlen im Bereich Low..High, 18.35 in Ihrem Beispiel.

Der falsche Weg, es zu tun so etwas wie wäre:

0..65536
r = (rand() % (High - Low + 1)) + Low 

rand() gibt eine Zahl in Bereich. Nehmen Sie den Rest nach dem Teilen durch (High - Low + 1), was in diesem Beispiel (35 - 18 + 1 = 18) ist. Das Ergebnis ist eine Zahl zwischen 0..17. Dazu fügst du Low (18) hinzu, was das Ergebnis r in den Bereich 18..35 verschiebt. Der Bereich , den Sie suchen.

Zahlen erzeugt auf diese Weise keine gleichmäßige Verteilung in den Fällen, wo der Divisor der Rest ist nicht ein geradzahliges Vielfaches der Obergrenze durch die Funktion rand() zurückgegeben zu erhalten, verwendet. Siehe die Fischer Yates Algorithm - Modulo Bias. Um diese Verzerrung zu entfernen, müssen Sie die größte Zahl berechnen, die kleiner als das ist, was rand() zurückgibt, aber gleichmäßig durch (High - Low + 1) teilt. In Ihrem Fall, dass von rand() wie folgt zurück auf die Zahlen 3640 * 18 = 65520. Verwenden Sie diese als Hochbereichsfilter ist:

do forever { 
    r = rand() 
    if r <= 65520 then { 
     r = (r % (High - Low + 1)) + Low 
     break 
     } 
    } 

nun die Zufallszahlen Sie die gleiche Verteilung haben generieren soll Eigenschaften wie rand().

+2

+1 für korrekte Mathematik. –

Verwandte Themen