2017-11-08 4 views
1

Dies ist eine Hausaufgabenfrage, aber es ist ein kleiner Teil eines viel größeren Projekts. Eine der Einschränkungen besteht darin, dass wir STL aus keinem Grund verwenden dürfen.Generieren von Zufallszahlen ohne Verwendung von CSTDLIB?

Ich habe versucht, meine eigene rand() -Funktion mit Ctime und einem inkrementierenden Modifikator zu rollen. Ich dachte mir, dass die Funktion, obwohl sie keinen konsistenten Anfangswert hat, Halb-Zufallszahlen ausgeben sollte, solange sie nicht mehr als einmal pro Sekunde denselben Modifikator erhält.

//notcstdlib.cpp 
//<ctime> <cmath> 
int rand(int mod) 
{ 
    time_t seed; 
    return std::abs(seed * mod); 
} 

aber dieser Beispielcode

//main.cpp 
#include "notcstdlib.h" 
#include <iostream> 

int main(int argc, char** argv) 
{ 
    int f; 
    for(int i = 1; i <= 10; i++) 
    { 
     f = rand(i); 
     std::cout << "random num= " << f << "\n"; 
     std::cout << "rand % 10 = " << f%10 << "\n"; 
    } 
    return 0; 
} 

Immer 7 als der erste Wert zurückgibt und nur gerade Zahlen zwischen 0 und 8 für jede andere Zahl.

//Output 1    //Output 2    //Output 3 
random num= 134514987 | random num= 134514987 | random num= 134514987 
rand % 10 = 7   | rand % 10 = 7   | rand % 10 = 7 
random num= 13261304 | random num= 24238584 | random num= 27941368 
rand % 10 = 4   | rand % 10 = 4   | rand % 10 = 8 
random num= 19891956 | random num= 36357876 | random num= 41912052 
rand % 10 = 6   | rand % 10 = 6   | rand % 10 = 2 
random num= 26522608 | random num= 48477168 | random num= 55882736 
rand % 10 = 8   | rand % 10 = 8   | rand % 10 = 6 
random num= 33153260 | random num= 60596460 | random num= 69853420 
rand % 10 = 0   | rand % 10 = 0   | rand % 10 = 0 
random num= 39783912 | random num= 72715752 | random num= 83824104 
rand % 10 = 2   | rand % 10 = 2   | rand % 10 = 4 
random num= 46414564 | random num= 84835044 | random num= 97794788 
rand % 10 = 4   | rand % 10 = 4   | rand % 10 = 8 
random num= 53045216 | random num= 96954336 | random num= 111765472 
rand % 10 = 6   | rand % 10 = 6   | rand % 10 = 2 
random num= 59675868 | random num= 109073628 | random num= 125736156 
rand % 10 = 8   | rand % 10 = 8   | rand % 10 = 6 
random num= 66306520 | random num= 121192920 | random num= 139706840 
rand % 10 = 0   | rand % 10 = 0   | rand % 10 = 0 

Offensichtlich fehlt mir etwas wichtiger Aspekt der rand() und ich bin der Umsetzung nicht. Gibt es einen besseren Weg, dieses Problem anzugehen?

+0

Ist die Aufgabe, einen eigenen Pseudozufallszahlengenerator zu schreiben? –

+0

Werfen Sie einen Blick hier: https://en.wikipedia.org/wiki/Linear-feedback_shift_register – DimChtz

+0

Siehe https://stackoverflow.com/questions/3062746/special-simple-random-number-generator –

Antwort

2

Sie sollen wahrscheinlich die Lehrer fragen, ob std::rand() auch ausgeschlossen ist und ob Sie wirklich Ihren eigenen Pseudo-Zufallszahlengenerator implementieren müssen. Oder besser, fragen Sie, ob Sie <random> verwenden dürfen, damit Sie die Mercene Twister-Engine von C++ verwenden können, die ein sehr guter Pseudozufallszahlengenerator ist.

Wenn Sie wirklich Ihre eigene müssen rollen, für std::rand() die einfachste Ersatz ist ein LCG (Kongruenzgenerator):

#define MY_RAND_MAX = 2147483647 
static unsigned long my_rand_state = 1; 

void my_srand(unsigned long seed) 
{ 
    my_rand_state = seed; 
} 

long my_rand() 
{ 
    my_rand_state = (my_rand_state * 1103515245 + 12345) % 2147483648; 
    return my_rand_state; 
} 

Sie dann my_srand(), my_rand() und MY_RAND_MAX wie würden Sie std::srand(), können std::rand() und RAND_MAX jeweils:

// Seed it with the current time. 
my_srand(std::time(nullptr)); 

// Print 1000 random numbers between 0 and MY_RAND_MAX. 
for (int i = 0; i < 1000; ++i) { 
    std::cout << my_rand() << ' '; 
} 
std::cout << '\n'; 

Dies erzeugt niedrige Qualität von Zufallszahlen (sie schlechte Verteilung haben.) Hinweis dass std::rand() hat auch eine schlechte Verteilung. Wenn Sie eine hohe Qualität von Zufallszahlen (dh gute Verteilung) haben möchten, sollten Sie die C++ <random> Algorithmen verwenden, mit dem std::mt19937 Motor (das ist der Mercene Twister-Algorithmus ist, die sehr gute Verteilung hat und einen großen Zeitraum.)

Im Allgemeinen vermeiden Sie einfach rand(). Siehe Stephan T. Lavavej's 30min talk "rand() Considered Harmful", ein Muss für jeden, der noch rand() in seinem Code verwendet.

+0

Ich werde versuchen, eine detailliertere Antwort vom Professor zu bekommen. In der Zwischenzeit werde ich mich wohl mit dem Großteil der Aufgabe beschäftigen. Was die Qualität betrifft, ist die Verteilung der Zahlen für diese Implementierung nicht allzu wichtig. Ich werde damit spielen und sehen, was ich damit machen kann. Vielen Dank. – anthony

+0

@anthony Ich bin sicher, du hast den Satz "Müll rein, Müll raus" schon gehört :-) Das heißt, wenn die Zufallszahlen wirklich schlecht sind, kannst du aus den Ergebnissen der Simulation schlechte Schlüsse ziehen. Wenn der einzige Sinn darin besteht, zu lernen, wie man eine Simulation macht, anstatt aus den Ergebnissen Schlussfolgerungen zu ziehen, ist das natürlich in Ordnung. –

+0

Ich mag diese Lösung. Es ist ziemlich einfach und es erlaubt mir, einen Seed vorzugeben und vorherige Zahlenreihen erneut auszuführen. Wenn ich Sie für eine weitere Erklärung stören könnte, habe ich versucht, verschiedene LCG-Nummern zu verwenden, und ich habe seltsame Ergebnisse bekommen. Ich habe versucht ((my_rand_state * 134775813 + 1)% 4294967296) und obwohl my_rand_state ist ein unsigned long, spuckte es manchmal negative Zahlen aus. Ich habe sogar my_rand() geändert, um explizit unsigned long zurückzugeben, aber nichts hat sich geändert. – anthony

2

Sie nie Ihre Samen initialisieren, versuchen

//notcstdlib.cpp 
<ctime> 
int rand(int mod) 
{ 
    static time_t seed = time(NULL); 
    return std::abs(seed * mod); 
} 
+1

Das ist eine beunruhigend einfache Unterlassung. Vielen Dank. – anthony

Verwandte Themen