2009-05-03 6 views
1

Jedes Mal, wenn ich die Funktion rand in C++ verwenden:Wie kann ich die Warnung mit rand() loswerden? (C++)

#include<iostream> 
#include<time.h> 
#include<stdlib.h> 
using namespace std; 
int main(){ 
srand(time(0)); 
int n=(rand()%6)+1; 
cout<<"The dice roll is "<<n<<"."<<endl; 
} 

ich eine Warnung über Umwandlung von Time_t erhalten in Zeile int 5:

srand(time(0)); 

Gibt es eine Möglichkeit, um loszuwerden, diese Warnung?

+2

Sie sollten und , denke ich, in C++ Code verwenden. –

+0

Warum das C-Tag für C++ entfernen? Die Frage bezieht sich auf srand() und time(), die aus der C-Sprache kommen. –

Antwort

8

Eigentlich sollten Sie eine eine unsigned int with srand() werden:

srand((unsigned) time(0)); 
+5

Pedantische Notiz - mit static_cast Formulierung für die Besetzung ist mehr Grep freundlich. – Anonymous

2

Verwenden Sie eine explizite Umwandlung der Warnung loszuwerden:

srand((int)time(0)); 
+1

Yecch. Dies hat ein Y2038-Problem, wenn time_t ein Double und Int ist 32 Bit. – Dave

+0

Nein Y2038-Problem - Sie sind nicht wirklich interessiert an dem genauen Datumswert, nur einige Semi-Zufallszahl, um den Zufallszahlengenerator mit zu säen. –

+0

Sie liegen falsch; Sobald der Wert von time_t 2^31 - 1 übersteigt, wird der Seed dort fixiert. – Dave

6

auf einem anderen Ton, dieser Code:

rand()%6 

wird allgemein als eine schlechte Praxis angesehen. die unteren Bits von rand() sind signifikant weniger zufällig als die höheren Bits. Sie erhalten eine bessere Zufälligkeit, wenn Sie folgendes tun:

(rand() >> 8)%6 

zum Beispiel.

EDIT:

Weitere Einzelheiten hierzu finden Sie this note und auch dieser Artikel von Dr. Dobbs Zeitschrift, die zumindest Hinweis auf den Grund:

Hinweis: Verwenden Sie KEINE

y = rand() % M; 

wie dies auf die unteren Bits von Rand() konzentriert. Für lineare Kongruenz zufällige Zahlengeneratoren, die rand() oft ist, sind die unteren Bytes viel weniger zufällig als die höheren Bytes. In der Tat das niedrigste Bit zwischen 0 und 1 Zyklen. So kann rand() zwischen geraden und ungerade (probieren Sie es aus). Anmerkung rand() muss nicht ein linearer kongruenter Zufallszahlengenerator sein. Es ist perfekt zulässig, damit es etwas besser ist, das dieses Problem nicht hat.

DDJ:

Der wichtigste Punkt ist, dass die unteren Bits der Ausgabe aus der üblichen (linearen Kongruenz) Zufallszahlengeneratoren die am wenigsten sind "random". Das heißt, Muster in den unteren Bits sind üblich. Daher ist die Ausgabe von der Routine in Ihrer Diskussion nicht überraschend. Außerdem ist es vermeidbar, indem man sich auf die oberen Bits bezieht, um die Ganzzahl zurückzugeben.

Zum Beispiel, wenn Sie wollten einen zufälligen „true“ oder „false“ Wert wählen, und Sie verwendete den Code:

rand() % 2 

Dann könnten Sie das Muster der Ergebnisse am Ende sehen:

1,0,1,0,1,0,1,0,1,0 (etc)

Dies ist offensichtlich nicht so zufällig, aber es ist eine Eigenschaft des Kongruenzgenerator, der in sein könnte benutzen. Ein besseres Schema (für C++) könnte die Verwendung der Boost.Random-Bibliothek sein, die Unterstützung für alle Arten von steckbaren Zufallsgeneratoren bietet (einschließlich Mersenne Twister, die diesen Fehler nicht aufweist).

+3

Könnte genauer ausgeführt werden (ich bin ziemlich neu mit C++) –

+0

Wenn Sie herausfinden möchten, warum einige Bits mehr zufällig als andere sind, habe ich keine Ahnung. Hört sich interessant an! Aber das >> ist eine Verschiebung. Nicht zu verwechseln mit seiner anderen Verwendung, die Sie wahrscheinlich gesehen haben (cin >> some_string_var). Stellen Sie sich vor, dass die Zahl im Binärsystem um 8 Bits nach rechts verschoben wird, wobei links Nullen erscheinen. Also 0110 1101 0001 0010 würde 0000 0000 0110 1101 werden. – MatrixFrog

+0

Ich habe die Antwort bearbeitet, um etwas mehr Details zu geben. –

2

Zwei seitliche Hinweise:

  • Die Standardmethode C-Header in C++ von darunter ist wie folgt: #include <cstdio>.
  • Der an time() übergebene Parameter ist ein Zeiger, und viele Leute denken, dass NULL ein besser lesbarer Nullzeiger als 0 ist. Auch
+0

In C++ verwenden viele Personen (Dr Stroustrup enthalten) lieber 0 als Nullzeiger. –

1

,

rand() % 6 

eine kleine Vorspannung einzuführen. Da RAND_MAX% 6 1 ist, werden Null und Eins etwas häufiger auftauchen als zwei bis sechs. In diesem Fall werden sie 5462-mal für 5461-mal zurückgegeben, die höheren Zahlen werden zurückgegeben, also werden Sie es wahrscheinlich nicht bemerken. Wenn jedoch der Bereich der gewünschten Zahlen groß ist, kann die Verzerrung signifikant sein. Wenn Sie zum Beispiel rand() % 32000 hätten, würde die Zahl im Bereich 0 - 767 doppelt so häufig erscheinen wie diese 768 - 32000.

+0

RAND_MAX% 6 ist eine Zahl zwischen 0 und 5, das ist alles, was man dazu sagen kann. Es gibt einen Grund dafür, dass es sich um ein Makro mit Implementierung handelt. – MSalters

+0

Die Einzelheiten können zwischen Implementierungen variieren, aber das Grundprinzip ist das Richtige. (Außerdem ist RAND_MAX == 32767 dem PC allgegenwärtig. Und selbst wenn Ihre Bibliothek einen anderen Wert verwendet, ist die Wahrscheinlichkeit, dass RAND_MAX% 6 == 5 - für keine Verzerrung benötigt wird - ziemlich niedrig). –

2

Um die Warnung loszuwerden, sollten Sie eine statische Umwandlung in eine Ganzzahl ohne Vorzeichen verwenden.

Zu einem verwandten Hinweis sollten die Ergebnisse von Rand nach rechts verschoben werden, um Verzerrungen in den unteren Bits zu entfernen.

int n = ((rand() >> 8) % 6) + 1; 

schließlich in C++ die C Zeit und Standardbibliotheken sollten enthalten sein wie:

#include <ctime> 
#include <cstdlib> 

Diese Funktionen in dem entsprechenden Namespace platzieren wird, 'std'.

Verwandte Themen