Ist Random doch nicht Random?

Für allgemeine Fragen zur Programmierung mit PureBasic.
Benutzeravatar
Thorium
Beiträge: 1722
Registriert: 12.06.2005 11:15
Wohnort: Germany
Kontaktdaten:

Beitrag von Thorium »

Ich glaub ich raff das net richtig. Wenn du jedesmal die gleichen Zahlen haben willst, warum generierst du sie dann überhaupt jedesmal neu?
Einmal generieren und dann in einer Tabelle speichern.
Zu mir kommen behinderte Delphine um mit mir zu schwimmen.

Wir fordern mehr Aufmerksamkeit für umfallende Reissäcke! Bild
Gubbie247
Beiträge: 32
Registriert: 10.10.2004 13:23

Beitrag von Gubbie247 »

ZeHa hat geschrieben:Das heißt, Du willst einfach nur 'ne Kurve, die krass aussieht, aber reproduzierbar ist?

Dann müßte es doch folgendermaßen funktionieren:

Code: Alles auswählen

RandomSeed(666)

Dim y(100)

For x = 0 to 100
    y(x) = Random(10)
Next x
Jetzt kannst Du in Zeile 1 jedesmal einen anderen Wert einsetzen, und bekommst auch jedesmal die passende Kurve. Die Kurve für 666 sieht aber immer gleich aus, und die Kurve für 667 sieht auch immer gleich aus. Ist es das, was Du brauchst?
womit wir dann exakt bei meiner ursprünglichen frage wären, da diese methode das Zackenmuster produziert
Benutzeravatar
Zaphod
Beiträge: 2875
Registriert: 29.08.2004 00:40

Beitrag von Zaphod »

Ok, jetzt verstehe ich was das Problem ist... du hast nicht begriffen, dass ein bestimmter Randomseed immer die selbe Reihenfolge von Zufallszahlen Produziert :lol:

Wenn du 1* RandomSeed ausführst auf eine Bestimmte Zahl, sagen wir mit seedwert 5, dann kommt immer die selbe Reihenfolge von Zufallszahlen beim Aufruf der Random Funktion.

Also du rufst 1* Randomseed(5) auf und die nächsten 10 000 000 Aufrufe von Random geben dir jedes mal die selben 10 000 000 Zufallszahlen zurück.
Benutzeravatar
Froggerprogger
Badmin
Beiträge: 855
Registriert: 08.09.2004 20:02

Beitrag von Froggerprogger »

Mir fallen 2 Sachen dazu ein:
1) Aus dem was Zaphod meint folgt auch, dass jedes Programm, welches zu Beginn den RandomSeed auf immer denselben Wert, z.B. 666 oder immer dieselben Werte, z.B. nach einem bestimmten Muster in einer for-Schleife setzt, sich bei jedem Durchlauf immer gleich verhält. Ich kann mir nicht vorstellen, dass das von dir gewünscht ist. Setze daher lieber sowas wie

Code: Alles auswählen

RandomSeed(ElapsedMilliseconds())
.

2) Fast alle Programmiersprachen (und garantiert auch PBs) haben als eingebauten Zufallszahlengenerator einen sogenannten linearen Kongruenzgenerator: http://de.wikipedia.org/wiki/Kongruenzgenerator
Diese sind schnell, aber haben ein paar unschöne Eigenschaften, insbesondere können sie bei geeigneter Darstellung oder Verwendung Muster verursachen, die echte Zufallszahlen nicht haben, z.B. Schräglinien in Punktwolken, etc. Es kann durchaus sein, dass genau dieses Verhalten für die Muster in deinem Problem verantwortlich ist. Gerade für zu niedrige Startwerte (Seeds) ist dieses extrem (z.B. sind die ersten Zufallswerte dann meist monoton steigend), daher sollte man lieber große Seeds nehmen (wie auch von ElapsedMilliseconds() oder sowas wie 100000 + 12345*i) geliefert). Für wissenschaftliche Anwendungen, oder generell welche, wo 'besserer Zufall' gewünscht ist, sollte man andere Zufallsgeneratoren nutzen, z.B. den Mersenne-Twister. Diese sind weit 'zufälliger' als der lineare, brauchen aber etwas mehr Rechenzeit.
!UD2
Benutzeravatar
dllfreak2001
Beiträge: 2925
Registriert: 07.09.2004 23:44
Wohnort: Bayern

Beitrag von dllfreak2001 »

Ich weiß ja net obs interessiert, hab mal in ner älteren Version von PB mit Randomseed rumgemacht. Da fiel mir auf, dass nur der Randomseed benutzt wurde der zuerst aufgerufen wurde egal wieviel man dannach ausführte. So musste ich um den Randomseed zu ändern das Programm neustarten.
Sollte ne Verschlüsselungsroutine werden und hab mich dann gewundert
als ich mit dem Passwort 1234 und auch dem paswort 195762 die Datei korrekt öffnen konnte.

Falls es interessiert...
I´a dllfreak2001
Benutzeravatar
#NULL
Beiträge: 2238
Registriert: 20.04.2006 09:50

Beitrag von #NULL »

@dllfreak
scheinbar gibt's das problem nicht mehr, insofern es mal existiert hat.

@Zaphod
das hatte er schon verstanden, und wollte es ja auch nutzten.

das problem ist einfach der Random-algo von PB, bzw das was FroggerProgger erklärt hat.
man kann das nur etwas verwischen, aber weg bekommt man es nicht.
hab Gubbie's code mal verändert. statt ordinalen seeds werden jetzt vorberechnete zufällige seeds berwendet.

Code: Alles auswählen

RandomSeed(1)
Global Dim rands.l(#bh*400)
For y=0 To #bh*400
  rands(y) = Random(#bh*400)
Next

;...

Procedure.f ran(x,y)
  ;RandomSeed(9999+rands(y))
  ;RandomSeed(Random(10000)+x)
  RandomSeed(rands(y)+x) : Random(1)
  ;For i = 0 To x
    l.f=-1+Random(2000)/1000
  ;Next
  ProcedureReturn l
EndProcedure

um eine andere formation zu erzuegen, den seedwert am anfang ändern.
komplett:

Code: Alles auswählen

InitSprite()
InitKeyboard()
InitMouse()

;#bb=1280 : #bh=800 : OpenScreen(#bb,#bh,32,"")
#bb=600 : #bh=400 : OpenWindow(0,100,100,#bb,#bh,"") : OpenWindowedScreen(WindowID(0),0,0,#bb,#bh,0,0,0)

RandomSeed(1)
Global Dim rands.l(#bh*400)
For y=0 To #bh*400
  rands(y) = Random(#bh*400)
Next

Procedure.f Cosine_Interpolate(a.f, b.f, x.f)
  ft.f = x * #PI
  f.f = (1 - Cos(ft)) * 0.5
  ProcedureReturn (a*(1-f) + b*f)
EndProcedure

Procedure.f ran(x,y)
  ;RandomSeed(9999+rands(y))
  ;RandomSeed(Random(10000)+x)
  RandomSeed(rands(y)+x) : Random(1)
  ;For i = 0 To x
    l.f=-1+Random(2000)/1000
  ;Next
  ProcedureReturn l
EndProcedure

Procedure.f noise(x.f,y.f)
  rand1.f=ran(Int(x),Int(y))
  rand2.f=ran(Int(x)+1,Int(y))
  rand3.f=ran(Int(x),Int(y+1))
  rand4.f=ran(Int(x)+1,Int(y+1))
  ProcedureReturn Cosine_Interpolate(Cosine_Interpolate(rand1 ,rand2,x-Int(x)),Cosine_Interpolate(rand3 ,rand4,x-Int(x)),y-Int(y))
EndProcedure

Procedure.f perlin(x.f,y.f,order)
  res.f=0
  For i = 1 To order
    res + noise(x*Pow(2,i),y*Pow(2,i))/Pow(2,i)
  Next
  ProcedureReturn res;noise(x,y)/2 + noise(x*2,y*2)/4 + noise(x*4,y*4)/8
EndProcedure


#Step=5
w=1
amp=100
CreateSprite(0,#bb,#bh)
CreateSprite(1,#bb,#bh)
StartDrawing(SpriteOutput(0))
For x = 1 To #bb-1

;  Debug x
Next
StopDrawing()

Repeat
 
  ExamineKeyboard()
  ExamineMouse()
  ClearScreen(RGB(0,0,0))
  For i = 0 To 10
  DisplaySprite(0,-1,0)
  StartDrawing(ScreenOutput())
  For y = 1 To #bh/2-1
    farbe.f=(0.5+0.5*perlin(time*00.01,y*00.01,10))*255
    If farbe>y
      farbe-y
      Plot(#bb-1,#bh-y*w,RGB(farbe,farbe,farbe))
    EndIf
  Next
  time+1
 
  StopDrawing()
  GrabSprite(0,0,0,#bb,#bh)
Next
  ;DisplaySprite(1,0,0)
  FlipBuffers()
Until KeyboardPushed(1)
my pb stuff..
Bild..jedenfalls war das mal so.
Benutzeravatar
dllfreak2001
Beiträge: 2925
Registriert: 07.09.2004 23:44
Wohnort: Bayern

Beitrag von dllfreak2001 »

Kannste mir gleuben :D das gab es mal...
Dann ist es wech war damals noch ne 3.xxxer
I´a dllfreak2001
Gubbie247
Beiträge: 32
Registriert: 10.10.2004 13:23

Beitrag von Gubbie247 »

#NULL hat geschrieben:@dllfreak

das problem ist einfach der Random-algo von PB, bzw das was FroggerProgger erklärt hat.
man kann das nur etwas verwischen, aber weg bekommt man es nicht.
hab Gubbie's code mal verändert. statt ordinalen seeds werden jetzt vorberechnete zufällige seeds berwendet. um eine andere formation zu erzuegen, den seedwert am anfang ändern.
komplett:
vielen dank für deine mühe, aber das löst das problem leider nicht.
hier hatte doch mal jemand eine alternative randomfunktion geschrieben, die ich leider nicht mehr finde.
Little John

Beitrag von Little John »

Ich habe mich jetzt etwas mit Perlin Noise beschäftigt, das ist ja sehr interessant! Gubbie247, vielen Dank dass Du das hier zur Sprache gebracht hast.
Ich glaube, ich verstehe jetzt auch einen Teil der Verwirrung die hier entstanden ist. Bei Perlin Noise geht es darum, reproduzierbares Rauschen zu erzeugen. Dafür braucht man eine Funktion, die scheinbar zufällige Werte liefert. Diese Funktion hat pro behandelter Dimension 1 Parameter, d.h. im 2-dimensionalen Fall sieht das so aus:

Code: Alles auswählen

Procedure.d PerlinNoise2D (x, y)
   ...
EndProcedure
Das ist aber etwas ganz anderes als PureBasics Random()-Funktion. Wichtig für Perlin-Rauschen ist, dass solch eine PerlinNoise()-Funktion für die selben Parameter immer das selbe Ergebnis liefert! Das ist bei Random() aber nicht der Fall. Für RandomSeed() trifft das zwar zu, aber RandomSeed() liefert keine (Pseudo-)Zufallszahlen, sondern das macht Random().

Was ist eine Zufallszahl? Ist z.B. 3 eine Zufallszahl? Die Frage ist so falsch gestellt. Man kann immer nur Serien von Zahlen nehmen und untersuchen, ob die Zahlen in einer Serie (annähernd) so verteilt sind, wie es auch der Fall wäre, wenn sie durch Zufall zustande gekommen wären. Random() liefert Serien von Zufallszahlen. Die Qualität hängt davon ab, wie lang die Periode ist (wie lange es dauert, bis Random() wieder anfängt die selben Zahlen zu liefern), und wie gut die Gleichverteilung der produzierten Zahlen ist (lässt sich z.B. mit dem Chiquadrat-Anpassungstest statistisch prüfen). Ohne solche Prüfungen gemacht zu haben, würde ich nicht behaupten dass hier irgendwas bei PureBasic nicht gut funktioniert.

Gubbie247 nimmt RandomSeed(). Weil diese Funktion keine Zahl zurückliefert, muss man anschließend noch mindestens 1x Random() aufrufen, also z.B.:

Code: Alles auswählen

Procedure.l Foo (seed.l, range.l)
   RandomSeed(seed)
   ProcedureReturn Random(range)
EndProcedure
Das entscheidende ist nun, dass (soweit ich weiß) niemand behauptet hat, dass die Werte die der wiederholte Aufruf solch einer Funktion Foo() zurückliefert, (pseudo)zufällig verteilt sind!

Am besten ist hier wohl -- wie oben auch schon vorgeschlagen wurde -- ein oder mehrere Arrays im Voraus zu berechnen, und diese dann im Programm zu verwenden. Der Erfinder, Prof. Perlin, macht es auch so. :)

Gruß, Little John
Benutzeravatar
#NULL
Beiträge: 2238
Registriert: 20.04.2006 09:50

Beitrag von #NULL »

geh auf den ersten link in dem post, und lade dir dort so eine datei herunter:
http://www.purebasic.fr/german/viewtopi ... 220#111220
dann kannst du deine random-werte aus dieser datei beziehen, und FileSeeks als Seeds verwenden.
my pb stuff..
Bild..jedenfalls war das mal so.
Antworten