#1 03.02.2005 13:38:03

Coolcat
ProGuru
Ort: Aachen, NRW
Registriert: 24.01.2005
Beiträge: 2780
Web-Seite

[C++] Zufallsgenerator

Zitat:

Die Standartbibliothek (in C++) stellt in <cstlib> und <stdlib.h> eine einfache Basis zur Generierung von Zufallszahlen zur Verfügung. (...) Das Erzeugen einer guten Zufallszahl ist nicht einfach, und leider besitzen nicht alle Systeme eine gute Funktion rand(). Speziell die niederwertigsten Bits einer Zufallszahl sind oft fragwürdig.

Um herauszufinden wieviele mögliche Werte die Funktion rand() liefert gibt es das Marco RAND_MAX, bei mir sind es gerade mal 32767, nicht umbedingt viel wenn man eine Double-Zufallszahl braucht.
Wem nun also die rand()-Funktion zu ungenau ist, kann diesen Zufallsgenerator benutzen. Er ist zwar langsamer, aber er liefert eine Zahl den kompletten Bereich eines DWORD ausnutzt.

Quelle: "Die C++ Programmiersprache", Bjarne Stroustrup
modifierziert von Coolcat.

Code:

// =============================================================================
// Zufallsgenerator Klasse
// =============================================================================


// C++Quellcode !!

#include "time.h"

typedef unsigned long DWORD; // 32 Bit, ohne Vorzeichen
typedef signed int INT32;    // 32 Bit, mit Vorzeichen

class CRandom &#123;
  DWORD dwRndX;
public&#58;
  CRandom&#40;&#41; &#123; dwRndX = &#40;unsigned&#41;time&#40; NULL &#41;; &#125; //Initialisieren
   
  void Init&#40;DWORD dwInit&#41; &#123; dwRndX = dwInit; &#125;   //Reinitialisieren
    
  INT32 Abs&#40;INT32 x&#41; &#123; return x & 0x7fffffff;  &#125;  //Vorz. &#40;Bit 32&#41; löschen 
    
  static double MaxInt&#40;&#41; &#123;       //return MaxInt + 1 &#40;nur Bit 32 gesetzt&#41;
    return double&#40;0x80000000&#41;; 
  &#125;

  INT32 Draw&#40;&#41; &#123;                     //nächste Zufallszahl
    return dwRndX = dwRndX * 1103515245 + 12345; 
  &#125;

  double fDraw&#40;&#41; &#123;                   //gibt eine Zufallszahl 0<=x<1
    return Abs&#40;Draw&#40;&#41;&#41;/MaxInt&#40;&#41;; 
  &#125;  

  double operator&#40;&#41;&#40;&#41; &#123;         //gibt fDraw&#40;&#41;;
    return fDraw&#40;&#41;; 
  &#125;

  INT32 operator&#40;&#41;&#40;INT32 iRange&#41; &#123;   //&#40;ganzzahlige&#41; Zufallszahl 0<=x<iRange
    return INT32&#40;double&#40;iRange&#41;*fDraw&#40;&#41;&#41;;
  &#125; 
&#125;;



Wer Lust hat kann diesen Zufallsgeneraotr natürlich gerne zu Delphi konvertieren... wink

Coolcat


My software never has bugs. It just develops random features.

Offline

 

#2 05.02.2005 10:40:12

theTux
Newbie
Registriert: 01.02.2005
Beiträge: 6

Re: [C++] Zufallsgenerator

Das kommt mir alles ziemlich kompliziert vor...


Warum nimmst Du nicht einfach ein Makro dafür?
Das wäre viel effizienter als eine eigene Klasse.

Außerdem ist es eh sinnvoller, wenn man die Zufallszahlengenerierung für den entsprechenden Zweck anpasst.


When you can read this, my post has finished.

Offline

 

#3 05.02.2005 13:07:17

Coolcat
ProGuru
Ort: Aachen, NRW
Registriert: 24.01.2005
Beiträge: 2780
Web-Seite

Re: [C++] Zufallsgenerator

1. Bei diesem Ding geht es nicht um effizientz, sondern um "bessere" Zufallszahlen. Braucht man viele Zufallszahlen, z.B. für ein Partikelsystem, so sollte man diese vorher generieren und in einem Array speichern (die Länge des Array's sollte eine Primzahl sein).

2. Im Buch sind es es sogar 3 Klassen... wink

3. Marcos sollten laut Bjarne Stroustrup nicht verwendet werden.

Man könnte aber eine inline-Funktion daraus basteln, werd ich mich vielleicht nachher mit beschäfitgen.... smile

Coolcat


My software never has bugs. It just develops random features.

Offline

 

#4 05.02.2005 15:17:51

Coolcat
ProGuru
Ort: Aachen, NRW
Registriert: 24.01.2005
Beiträge: 2780
Web-Seite

Re: [C++] Zufallsgenerator

Sooo, ich hoffe das funzt so, hab nich alzu viel dran rumgetestet...

Die Lösung mit der Default-Variable gefällt mir auch nicht wirklich, aber irgendwie muss man ja die static-Variable inizialisieren. Ich denke allerdings das ein halbwegs intelligenterCompiler das wegoptimiert. Natürlich könnte man auch einfach eine globale Variable und 2 Funktionen benutzen...

Code:

#include <iostream>
#include <time.h>

typedef unsigned long DWORD; // 32 Bit, ohne Vorzeichen
typedef signed int INT32;    // 32 Bit, mit Vorzeichen

//Zufallszahl &#40;voller INT32-Bereich&#41;
inline INT32 rndDraw&#40;bool bDoInit = false&#41; &#123;
  static DWORD dwValue;
  if &#40;bDoInit&#41; &#123;
    dwValue = &#40;unsigned&#41;time&#40; NULL &#41;;
  &#125;
  return dwValue = dwValue * 1103515245 + 12345;
&#125;

//Zufallszahl 0<=x<1
inline double random&#40;&#41; &#123;                 
  return &#40;rndDraw&#40;&#41; & 0x7fffffff&#41; / double&#40;0x80000000&#41;;
&#125;

//&#40;ganzzahlige&#41; Zufallszahl 0<=x<iRange
inline INT32 random&#40;INT32 iRange&#41; &#123;                 
  return INT32&#40;double&#40;iRange&#41;*random&#40;&#41;&#41;;
&#125;


// Beispiel&#58;
int main&#40;int argc, char *argv&#91;&#93;&#41;
&#123;
  rndDraw&#40;true&#41;;
  for &#40;int i=0; i< 100; i++&#41; &#123;
    std&#58;&#58;cout << random&#40;&#41; << 'n';
  &#125;
   
    system&#40;"PAUSE"&#41;;  
    return 0;
&#125;



Coolcat


My software never has bugs. It just develops random features.

Offline

 

Brett Fußzeile

Powered by PunBB
© Copyright 2002–2005 Rickard Andersson