Programmieren - alles kontrollieren 4.941 Themen, 20.715 Beiträge

Zufallszahlen in (V)C(++)

SeeksTheMoon / 4 Antworten / Baumansicht Nickles

Moin!
Ich hab eine Funktion geschrieben, die mir Zufallszahlen im Bereich 1-6 liefern soll, aber irgendwie habe ich das Gefühl, dass die Zahlen ein bestimmtes Muster bilden, obwohl ich die Funktion von der Systemzeit abhängig gemacht habe:

...

int wuerfel()
{
time_t t;
srand((unsigned) time(&t));
return ((int) (rand() %10)*0.6+1);
}

...

Liegts am Algo oder was? Er ist nicht gerade der hit, aber er sollte eigentlich ausreichen.
Kennt jemand eine bessere Methode, die nicht zu lang/komplex ist?

bei Antwort benachrichtigen
Dreamforger SeeksTheMoon „Zufallszahlen in (V)C(++)“
Optionen

Kurzantwort:

Versuchs mal mit
return (int)(rand() % 6);


Langantwort:

1. Fehler : 1 bis 6 sind nicht gleichwarscheinlich
Dein Alg betrachtet eigentlich nur die letzte Ziffer des 'rand' Wertes. Diese letzte Ziffer ist mit gleicher Wahrscheinlichkeit 1/10 eine Ziffer 0 bis 9.
Danach wird jede der 10 Ziffern auf eine Ziffer im Bereich 1 bis 6 abgebildet.
Die Wahrscheinlichkeit für ein eine Ziffer zwischen 1 und 6 ist damit abhängig von der Anzahl der Ziffern zwischen 0 und 9 die auf sie abgebildet werden.

Anschaulich:
links steht die letzte Ziffer der 'rand' Zahl, rechts der Würfel
0 , 1 -> 1 (2/10 ~ 1/5 anstatt 1/6) zu oft
2 , 3 -> 2 (2/10 anstatt 1/6) zu oft
4 -> (1/10 anstatt 1/6) zu selten
5 , 6 -> 4 (2/10 anstatt 1/6) zu oft
7 , 8 -> 5 (2/10 anstatt 1/6) zu oft
9 -> 6 (1/10 anstatt 1/6) zu selten

Dazu kommt noch das die Ziffern 0 bis 9 schon nicht gleichverteilt sind da die grösste mögliche Zahl 2^32 nicht auf 9 endet, das kann man aber vernachlässigen

Lösung:
return (int)(rand() % 6);


2.Fehler
Du nimmst an das es sich wirklich um Zufallszahlen handelt. Es handelt sich jedoch nur um Pseudozufallszahlen da bei gleicher srand initialisierung dieselbe Kette von Werten generiert wird.
Dagegen lässt sich leider nichts (in Worten: nix) machen :-( da nicht-determinismus der Natur des Computers wiederspricht. Will heissen: eigentlich sollte bei gleicher Eingabe immer dasselbe rauskommen. Echten Zufall gibt's am Computer nicht.

Andererseits:
Sooo viele Variationsmöglichkeiten gibt es nun auch wieder nicht Folgen von Ziffern 1 bis 6 zu bilden. Und Sequenzen wie 123456, 666 , u.ä sind auch einfach zufällig. Lass dir doch mal 10 Zahlen ausgeben und versuch sie dann zu verändern so dass du kein Muster mehr feststellen kannst. Hast du dann noch Sequenzen von aufsteigenden, abfallenden oder gleichbleibenden Ziffern? Wahrscheinlich nicht, aber ist das dann noch Wirklich Zufall....
Ich fang jetzt nicht an zu Philosophieren....

Tapfer so viel zu lesen :-)
Ich hoffe es war nicht zu viel unverständliches Geschwalle...

Dreamforger


bei Antwort benachrichtigen
SeeksTheMoon Nachtrag zu: „Zufallszahlen in (V)C(++)“
Optionen

thx. Mit der Wahrscheinlichkeit, da hätte ich auch drauf kommen sollen (kein tolles Zeugnis für einen Informatiker, hm?).

Dass rand nur pseudo liefert ist schon klar, dafür ist ja der Zeitfaktor mit eingebaut.

Klaro sind die Frequenzen zufällig, aber nicht, wenn sie sich jedes 4. mal wiederholen (wenn man sich den Bereich noch auf 20 und 100 erweitert und alle drei Varianten zusammen laufen lässt, dann fällt es besonders stark auf).

Ich hab übrigens auf planet-source-code einen fetten Algo gefunden, der "echte" Zufallszahlen generiert, aber für quick and dirty reicht meiner ja allemal aus.

cu

bei Antwort benachrichtigen
Anonym SeeksTheMoon „Zufallszahlen in (V)C(++)“
Optionen

Neben den schon angeführten Schwächen, noch ein Einwurf von mir:

Die Funktion hat eine grosse Schwachstelle: Die Zufallszahlen
lassen sich erraten, bzw. der Wertebereich der Zufallszahlen
laesst sich stark eingrenzen, da der Startwert des Zufallsgenerators
bei jedem Funktionsaufruf neu gesetzt wird.

mfg. j.

bei Antwort benachrichtigen
(Anonym) SeeksTheMoon „Zufallszahlen in (V)C(++)“
Optionen

Ich will noch einen kleinen Tp geben, den ich selbst schon angewendet habe: Erzeuge in einem Array mit dem Generator 10000 oder 100000 Zahlen und zähle dann die Anzahl jeder Zufallszahl. Damit erhälst Du eine bombensichere Aussage darüber ob wirklich der Zufall regiert.

Gruß


bei Antwort benachrichtigen