# besserer Zufallszahlengenerator als srand/rand



## Tetse (20. Oktober 2005)

Hat jemand ein Codeschnipsel von einem zuverlässlicheren Zufallsgenerator, der "echtere" Zufallszahlen liefert, als die konventionelle Methode mit srand und rand?
Sollte möglichst einfach zu implementieren sein. Wäre sehr dankbar!


----------



## C Coder (20. Oktober 2005)

Was verstehst du denn unter  "echteren" Zufallszahlen bzw. warum willst du rand() nicht nutzen?


----------



## Tetse (20. Oktober 2005)

Meine Frage mit einer Frage zu beantworten....
Weil es den Anschein hat, dass die Pseudozufallszahlenfolgen die mir von rand ausgespuckt werden, sehr kurz sind und sich deshalb immer wiederholen. Wenn ich diese Zahlenfolgen nun visualisiere kommt dann stets das gleiche Bild heraus.
btw. ich versuche sowas wie diese "Wolken" (in den Filtern) aus Photoshop zu generieren.


----------



## CodeFatal (20. Oktober 2005)

Hi,
Unter Win. gibts zwar echte Zufallszahlen aber da ist super schwer dran zukommen. 
Weiß zwar nicht mehr wie aber google weiß es  musst nur super Glück haben...

Um dein Problem zu lösen sollte aber Rand ausreichen. 
Hast du srand() mit der Aktuellen System Zeit initialisiert - damit ist dann ein wiederholen der Sequenz schon mal so gut wie ausgeschlossen?
rand() liefert dann immer ne zahl zwischen 0 und RAND_MAX- Das sind bei WinXP immerhin 2^32 Möglichkeiten.

poste evt. mal deinen Schnipsel

Gruss Michael


----------



## mueslirocker (20. Oktober 2005)

Kann mir auch vorstellen, dass deine Visualisierung immer in etwa gleich aussieht, weil Zufallszahlen im Mittel immer die gleiche Summe bilden (also theoretisch).
Und wenn man genug Zahlen einfließen lässt (also das Bild weit genug unterteilt).. wie z.B. beim Rauschen, in dem du die Farbwerte jedes Pixels einzeln zufällig bestimmst, wird selten etwas anderes als Konfetti herauskommen.
Wenn man nur wenige Zufallszahlen mit großer Bandbreite einfließen lässt, weicht man eher mal vom Mittelwert ab.
Was das mit dir zu tun hat, kann ich leider nicht sagen, weil ich Photoshop nicht benutze und daher diesen Effekt nicht kenne.

Naja, eigene Zufallszahlen.
Ich kenn da noch das Quadrat-Mittel-Verfahren aus der Schulzeit.
Du nimmst eine vierstellige Zahl, quadrierst sie, füllst mit führenden Nullen auf 8 Stellen auf und nimmst dann die Stellen 3 bis 6 raus. Das sind deine nächsten Zufallszahlen und das ist die Zahl, die du dann weiter quadierst.
Glaube aber nicht, dass das Verfahren besser ist, als der Standard... zumal nach spätestens 9999 Zahlen die Reihe von Vorne beginnen muss... der Zufall setzt da ja schon aus, wenn du die gleiche Zahl nochmal generierst, da du nur mit ihr weitermachst. Es kommt also auch auf den Startwert an... und das spricht wohl gegen dieses Verfahren.


----------



## Tetse (20. Oktober 2005)

Hier ist der Codeausschnitt. iter sollte bei etwa 500000 liegen


```
void DrawClouds(HDC hdc, int iter)

{
	int x0 = rect.left+100;
	int y0 = rect.top+100;
	const int xy = 500;
	float pxy[xy][xy];
	int x, y, dir;

	for (int i=0; i<xy; i++)
		for (int j=0; j<xy; j++)
			pxy[i][j] = 0;	
	
	srand(time(0));

	x = rand() % 500;
	y = rand() % 500;

	for (i=0; i<iter; i++)
	{		
		dir = (rand() % 8);			

		if (dir==0)
			x+=1;
		else if (dir==1)
			x-=1;
		else if (dir==2)
			y+=1;
		else if (dir==3)				
			y-=1;
		else if (dir==4)
		{
			x+=1;
			y+=1;
		}
		else if (dir==5)	
		{
			x-=1;
			y-=1;
		}
		else if (dir==6)				
		{
			x+=1;
			y-=1;
		}
		else if (dir==7)
		{
			x-=1;
			y+=1;				
		}
	
		if (x>xy-5)
			x = 5;
		if (x<5)
			x = xy-5;
		if (y>xy-5)
			y = 5;
		if (y<5)
			y = xy-5;
		if (pxy[x][y] < 1)
			pxy[x][y] += 0.1;

//SetPixel(hdc, x0 + x, y0 + y, RGB(255,0,0));
	}

	for (i=0; i<xy; i++)
		for (int j=0; j<xy; j++)
			SetPixel(hdc, x0 + i, y0 + j, RGB(255-255*pxy[i][j], 255-255*pxy[i][j], 255-255*pxy[i][j]));		
}
```

Es bildet sich danach letztlich immer das gleiche Bild. In der Programmierung kann ich keinen Fehler finden. Es kann natürlich sein das ich blind bin...


----------



## deepthroat (20. Oktober 2005)

Hi.

Das Problem ist wie du die Werte die rand() zurückgibt verwendest. Um Werte im Bereich 0 bis 499 zu erhalten sollte man niemals den Modulo Operator verwenden wie du das gemacht hast.

Sondern so:
	
	
	



```
/* get integer random number in range a <= x <= e */
int irand( int a, int e)
{
    double r = e - a + 1;
    return a + (int)(r * rand()/(RAND_MAX+1.0));
}
```

Siehe z.B. http://cplus.kompf.de/artikel/random.html

Wenn du eine andere Verteilung für deine Zufallszahlen möchtest, kannst ja mal einen Blick auf die Boost Random Number Library oder auf die Blitz++ Bibliothek (http://www.oonumerics.org/blitz/).

Echte Zufallszahlen kannst du nicht durch ein Programm generieren sondern nur durch andere Hilfsmittel wie z.B. eine Lava-Lampe. Es gibt mehrere Seiten im Internet die echte Zufallszahlen zur Verfügung stellen - z.B. http://www.random.org die die Zahlen vom athmosphärischen Rauschen erzeugen.

Gruß


----------



## CodeFatal (20. Oktober 2005)

Lass mich mal raten: Da entsteht irgendwo ein Fleck auf dem Monitor, immer an ner anderen Stelle, normaler weise keine Ausreisser, relativ rund. 

Falls dem so ist liegt das daran, das man im Mittel genau so oft links wie rechts geht, soll ehissen, du toggelst mehr oder weniger um deinen Startwert, der bei 
	
	
	



```
x = rand() % 500;
y = rand() % 500;
```
rauskommt.

Wie ist denn genau dein Ziel? so ganz hab ich das noch nicht verstanden.
Vielleicht mal nen Bild von deinen Photoshop Wolken hochladen...

Gruss Michael


----------



## jsendrow (20. Oktober 2005)

http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html


----------



## Tetse (20. Oktober 2005)

@deepthroat

Danke! Ich hatte die Codezeile mit Modulo irgendwann einmal aus einem anderen Codeschnipsel übernommen und mir kam überhaupt nicht der Gedanke es anzuzweifeln. Es sieht jetzt zumindest so aus wie ich es mir vorgestellt habe:

http://home.arcor.de/tetsuwan/Wolken.jpg

Noch nicht ganz perfekt, aber das lässt sich noch machen.

Bei der Variante mit Modulo Operator hat sich nach einer gewissen Anzahl an Schleifendurchgängen eine gewisse Saturierung des Bilds eingestellt - es wurden immer die gleichen Zufallszahlensequenzen geliefert. Aber wie kann das passieren? Der Nachkommaanteil wird ja immer weggeschnitten, aber soll dass allein schon dafür verantwortlich sein?

random.org etc. hatte ich mir schon vorher angeschaut, auch den Mersenne Twister, da ich aber bei den Quellcodes auf die Schnelle net richtig durchgesehen hab, wollte ich eben erstmal etwas einfacheres versuchen und hier nachfragen 

@CodeFatal

Hmm, nö, du kannst ja mal so was ähnliches nachprogrammieren. Es soll im Grunde genommen eine vereinfachte Brownian Motion sein.Damit lässt sich auch so etwas wie Algenwachstum o.ä. nachbilden. Siehe http://de.wikipedia.org/wiki/Diffusionsbegrenztes_Wachstum


----------



## deepthroat (21. Oktober 2005)

Hi.



			
				Tetse hat gesagt.:
			
		

> Bei der Variante mit Modulo Operator hat sich nach einer gewissen Anzahl an Schleifendurchgängen eine gewisse Saturierung des Bilds eingestellt - es wurden immer die gleichen Zufallszahlensequenzen geliefert. Aber wie kann das passieren? Der Nachkommaanteil wird ja immer weggeschnitten, aber soll dass allein schon dafür verantwortlich sein?


Also Moment. Es gibt bei der Ganzzahldivision keinen Nachkommateil sondern nur den ganzzahligen Quotienten und Rest. Der Modulo Operator liefert dir also den Rest der Division. Das Problem mit dieser Operation bei den Zufallszahlen ist das nur die niederwertigen Bits für das Ergebnis wichtig sind. D.h. obwohl rand() völlig verschiedene Zahlen liefert (z.B. ganz große und ganz kleine) ist das Ergebnis der Modulo Operation für viele dieser Zahlen gleich - obwohl sie völlig verschieden sind.  Das wird durch den Code in der irand() Funktion vermieden, da erstmal das Ergebnis der rand() Funktion um die Größe des Intervalls gestreckt wird und dann dividiert wird. So kommt eine große Zufallszahl des entsprechenden Intervalls zustande wenn rand() eine große Zahl geliefert hat, und eine kleinere Zahl wenn rand() eine kleine Zahl liefert.

Ich hoffe ich hab mich da jetzt irgendwie verständlich ausgedrückt.. 

Gruß


----------

