Forum: PC Hard- und Software visual studio c++ Zufallszahlen


von Frodo (Gast)


Lesenswert?

Ich versuche mich gerade an einer Routine die Zufallszahlen zu Verfügung 
stellen soll.
rand mit Referenz an srand(time) bringt keine zufriedenstellene 
Ergebnisse, hier kann man ständing eindeutige Tendenzen erkennen.

Gibt es überhautp einigermaaßen funktionierende Lösungen?

von Random .. (thorstendb) Benutzerseite


Lesenswert?

Beim C64 konnte man afaik ein Rauschregister im SID auslesen :-) :-) :-)

Naja, dass die Zufallszahlenfolgen reproduzierbar sind, ist ja auch 
gewollt, und wird bei jeder algorhytmik so sein.

Vielleicht bringt es mehr Chaos ins System, das tiefer zu schachteln 
bzw. den seed nochmals zu verändern?

: Bearbeitet durch User
von Dirk K. (merciless)


Lesenswert?


: Bearbeitet durch User
von rbx (Gast)


Lesenswert?


von mh (Gast)


Lesenswert?

rbx schrieb:
> noch mehr zu lesen:
> 
https://www.c-plusplus.net/forum/topic/172876/zufälle-gibt-s-funktionen-rund-um-rand-random-und-den-zufall

cstdlib und rand sind allerdings eher C auch wenn es im C++ Standard 
steht. merciless hat die relevanten C++ Links gepostet.

von loeti2 (Gast)


Lesenswert?

Weil hier es um Pseudozufallszahlen geht:
1
#include <random>
2
3
int GetRandom0_5 () {
4
  std::default_random_engine generator;
5
  std::uniform_int_distribution<int> distr(0, 5); // range is inclusive
6
  return distr(generator);
7
}

Was wird diese Funktion wohl liefern ;-)

Meine Frage, wie schreibe ich am besten eine Funktion, die von 
verschiedenen Aufrufern aufgerufen wird, und jedem Aufrufer (unabhängig 
von der Aufrufreihenfolge), eine Zahlenfolge liefert die die Kriterien 
der "Pseudozufälligkeit" erfüllt.

Habe bis jetzt keine befriedigende Antwort gefunden. D.h. zur Zeit baue 
ich jeweils einen neuen Generator/Distribution in die Verwenderfunktion 
ein, so:
1
#include <random>
2
3
void SomeFunction(/*params*/) {
4
  // need a random int 0..5
5
  std::default_random_engine generator;
6
  std::uniform_int_distribution<int> distr(0, 5); // range is inclusive
7
  for (;;) { // loop which need random numbers
8
     ...
9
     int r= distr(generator);
10
     ...
11
  }
12
}

von Sven B. (scummos)


Lesenswert?

Du initialisierst den Generator nur einmal und nimmst dann einfach immer 
vom selben Generator Werte. Wenn du neu seedest mit der Zeit oder sowas, 
kriegst du natürlich immer dieselben bis sich die Zeit ändert. Die 
Verteilung ist nur dann gut, wenn du nur einmal seedest.

von Rolf M. (rmagnus)


Lesenswert?

Frodo schrieb:
> rand mit Referenz an srand(time) bringt keine zufriedenstellene
> Ergebnisse, hier kann man ständing eindeutige Tendenzen erkennen.

Was verstehst du unter "eindeutige Tendenzen"? Normalerweise sind die 
üblichen PRNGs gut genug, solange man es nicht als Basis für 
Verschlüsselung oder ähnliches verwenden will.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Rolf M. schrieb:
> Was verstehst du unter "eindeutige Tendenzen"?

Man muss aufpassen, dass man durch eine Skalierung die Verteilung nicht 
verschiebt. Das klassische "rand() % 42" liefert keine Gleichverteilung.

Die C++ "random" Bibliothek macht es einfach, korrekt gleichverteilte 
(oder anders verteilt, z.B. Normalverteilung) Zahlen zu erzeugen.

loeti2 schrieb:
> Habe bis jetzt keine befriedigende Antwort gefunden. D.h. zur Zeit baue
> ich jeweils einen neuen Generator/Distribution in die Verwenderfunktion
> ein, so:

Das ist eigentlich genau richtig so. Die zwei Zeilen am Anfang 
erscheinen zwar "überflüssig", aber sie definieren eben genau für 
welchen Bereich die Zufallszahlen gelten.

Du kannst die Objekte global machen:
1
static std::default_random_engine generator;
2
static std::uniform_int_distribution<int> distr(0, 5); // range is inclusive
3
4
int GetRandom0_5 () {
5
  return distr(generator);
6
}

sodass die Verteilung für alle Aufrufer gilt. Finde ich aber nicht 
wirklich besser.

von Frodo (Gast)


Lesenswert?

ich hab noch weiter herumexperimientiert, bin aber bislang zu keinem 
zufriedenstellenden Ergebnis gekommen.
Es gibt in einem Rechner dorch einige durchaus nicht vorhersehbare 
Signale wie Microphone Eingang, Temperatur, Lüftergeschwindigkeit, Wlan 
Signal Stärke, PSU Spannungen usw.

Warum nimmt man nicht die zur Hand, anstatt der Uhr, die sehr wohl 
"vorhersehbar" ist...

von Sven B. (scummos)


Lesenswert?

Was willst du denn überhaupt? Willst du eine Sequenz zufällig verteilter 
Zahlen, oder willst du kryptographischen Zufall, oder ...?

von Rolf M. (rmagnus)


Lesenswert?

Frodo schrieb:
> ich hab noch weiter herumexperimientiert, bin aber bislang zu keinem
> zufriedenstellenden Ergebnis gekommen.

Du hast leider deine Anforderungen immer noch nicht genannt, oder in 
welcher Form die Ergebnisse diesen nicht genügen, oder wie dein Code, 
der die Zahlen generiert, denn aussieht.

> Es gibt in einem Rechner dorch einige durchaus nicht vorhersehbare
> Signale wie Microphone Eingang, Temperatur, Lüftergeschwindigkeit, Wlan
> Signal Stärke, PSU Spannungen usw.
>
> Warum nimmt man nicht die zur Hand, anstatt der Uhr, die sehr wohl
> "vorhersehbar" ist...

Weil es dabei nicht darum geht, ob die Zahl vorhersehbar ist, sondern 
nur darum, dass sie nicht immer gleich ist. Die von dir genannten Dinge 
sind alle umständlicher einzulesen und nicht zwingend bei jedem System 
in gleicher Form vorhanden.
Und wenn deine Initialisierung nicht vorhersehbar ist, bringt dir das eh 
nichts, weil sobald du die erste Zahl gesehen hast, alle weiteren doch 
wieder vorhersehbar sind.
Wenn man höhere Qualität der Zufallszahlen will, muss man sowas nehmen:
https://de.wikipedia.org/wiki//dev/random
Ob's da ein vergleichbares Windows-Pendant gibt, weiß ich nicht.

Oder vielleicht auch das:
https://en.wikipedia.org/wiki/RdRand
Dafür gibt's auch eine Lib:
https://software.intel.com/en-us/articles/the-drng-library-and-manual
Das ist dann aber natürlich auf die Prozessoren beschränkt, die das 
können.

: Bearbeitet durch User
von Dirk K. (merciless)


Lesenswert?

Warum sagst du uns nicht einfach, für was du die
Zufallszahlen benötigst und in welchem Wertebereich
die liegen sollen?

merciless

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Frodo schrieb:
> ich hab noch weiter herumexperimientiert, bin aber bislang zu keinem
> zufriedenstellenden Ergebnis gekommen.

Definiere "zufriedenstellend".

Frodo schrieb:
> Warum nimmt man nicht die zur Hand, anstatt der Uhr, die sehr wohl
> "vorhersehbar" ist...

Kann man. Es gibt aber durchaus Situationen bei denen die 
"Zufalls"zahlen vorhersehbar sein sollen - daher nennen die sich auch 
Pseudozufallszahlen. Die von rand() und "<random>" generierten Zahlen 
fallen darunter. Diese sehen aber nicht vorhersehbar aus - sie sind 
statistisch so verteilt wie "echte" gleichverteilte Zufallszahlen. 
Aufgrund dieser Garantien ist es fragwürdig, wie du hier "eindeutige 
Tendenzen" und "nicht zufriedenstellende" Zahlen erkennen willst - wenn 
man den Algorithmus nicht kennt, kann man (gute) Pseudozufallszahlen 
kaum von echten Zufallszahlen unterscheiden.

Typischerweise kann man viel mehr Pseudozufallszahlen viel einfacher pro 
Sekunde erzeugen als echte Zufallszahlen. Für z.B. so etwas wie das 
Verhalten NPC's in Computerspielen oder Simulation von Partikeln für 
Grafikeffekte ist das genau richtig, für die Erzeugung von Passwörtern 
eher nicht. Mit std::random_device bietet C++ auch die Möglichkeit, 
echte Zufallszahlen zu erzeugen.

Daher: Du musst wissen was du überhaupt brauchst...

von Nils (Gast)


Lesenswert?

Da Du eh unter Windows unterwegs bist, nimm einfach rand_s und gut.

https://docs.microsoft.com/de-de/cpp/c-runtime-library/reference/rand-s?view=vs-2019

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Nils schrieb:
> Da Du eh unter Windows unterwegs bist, nimm einfach rand_s und gut.

Die liefert aber genauso eine Pseudozufallszahl wie rand() und die C++ 
random Bibliothek, ist nicht portabel, ermöglicht nicht die 
Spezifikation von Min/Max und der Verteilung. Hat also keine Vorteile 
gegenüber der Antwort von loeti2 (std::uniform_int_distribution und 
std::default_random_engine).

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.