Seite 1 von 1

normal verteilte Zufallszahlen

Verfasst: 20.02.2009 21:36
von Berti27
Hallo erstmal!
Habe mal alles in einem ausführbaren Progrämmchen zusammengetragen, was ich jemals bei Zufallszahlen in Codes geschrieben habe. Vielleicht kann das ja jemand gebrauchen.

Code: Alles auswählen

; PureBasic Visual Designer v3.95 build 1485 (PB4Code)
;Das folgende kleine Programm wurde in Vorbereitung eines größeren geschrieben, um die Einflussfaktoren der Variablen besser
;beurteilen zu können. Die erzeugten Zufallwerte werden dabei mit der Theorie verglichen. Erzeugt werden gleichverteilte 
;und normalverteilte Zufallszahlen(nach drei Methoden). Alles weitere steht im Code.
;Interessant ist, dass bei der Erzeugung nach dem Grenzwertsatz (Zwölferregel) die Geauigkeit mit ungeraden "Anzahl-Werten" 
;größer ist, was auch optisch sehr ins Auge fällt.
;Durch empirische Ermittlungen habe ich Korrekturfaktoren gefunden, die in dem von mir betrachteten Wertebereich gute Ergebnisse
;liefern. Inwieweit sie Mathematisch jedoch korrekt sind, kann ich nicht beurteilen, da mir das Wissen dazu fehlt.

Enumeration
  #Window_0
EndEnumeration

;- Gadget Constants
;
Enumeration
  #Button_0
  #Button_1
  #Button_2
  #Button_3
  #Text_0
  #Text_1
  #Text_2
  #Text_3
  #Text_4
  #Text_5
  #Text_6
  #Text_7
  #Text_8
  #Text_9
  #Text_10
  #Text_2a
  #Text_3a
  #Text_5a
  #Text_6a
  #String_0
  #String_1
  #String_2
  #String_3
  #Frame_0
EndEnumeration
Dim Wert(99,1)

Procedure Open_Window_0()
  If OpenWindow(#Window_0, 216, 0, 600, 300, "Zufall mit System", #PB_Window_SystemMenu | #PB_Window_TitleBar | #PB_Window_ScreenCentered)
      ButtonGadget(#Button_0, 10, 80, 160, 20, "Gleichverteilt")
      ButtonGadget(#Button_1, 10, 104, 92, 20, "Grenzwertsatz")
      ButtonGadget(#Button_2, 10, 128, 160, 20, "Polar-Methode") 
      ButtonGadget(#Button_3, 10, 152, 160, 20, "Box-Muller-Algorithmus")    
      TextGadget(#Text_0, 190, 284, 400, 20, "0                                                             50                                                          100")
      StringGadget(#String_0, 134, 10, 36, 16, "4000",#PB_Text_Right|#PB_String_Numeric)
      StringGadget(#String_1, 134, 30, 36, 16, "50",#PB_Text_Right)
      StringGadget(#String_2, 134, 50, 36, 16, "16",#PB_Text_Right)
      StringGadget(#String_3, 144, 106, 26, 16, "12",#PB_Text_Right)
      TextGadget(#Text_1, 10, 10, 90, 16, "Anzahl der Werte")
      TextGadget(#Text_2, 20, 216, 110, 16, "Erwartungswert")
      TextGadget(#Text_3, 20, 236, 110, 16, "Standardabweichung")
      TextGadget(#Text_4, 20, 196, 110, 16, "mittl. Abweichung (%)")
      TextGadget(#Text_5, 20, 256, 110, 16, "Extreme < 0")
      TextGadget(#Text_6, 20, 276, 110, 16, "Extreme > 99")
      TextGadget(#Text_7, 10, 30, 110, 16, "Erwartungswert")
      TextGadget(#Text_8, 10, 50, 110, 16, "Standardabweichung")
      TextGadget(#Text_2a, 124, 216, 36, 16, "?",#PB_Text_Right)
      TextGadget(#Text_3a, 124, 236, 36, 16, "?",#PB_Text_Right)
      TextGadget(#Text_5a, 124, 256, 36, 16, "?",#PB_Text_Right)
      TextGadget(#Text_6a, 124, 276, 36, 16, "?",#PB_Text_Right)
      TextGadget(#Text_9, 90, 108, 50, 16, "Anzahl:",#PB_Text_Right)
      TextGadget(#Text_10, 124, 196, 36, 16, "?",#PB_Text_Right)
      Frame3DGadget(#Frame_0,10,176,160,120,"errechnete Werte")
      StartDrawing(WindowOutput(0)) ;der Einfachheit halber, statt eines Image-Gadgets
    		Box(181,4,413,276,$000000)
    		Box(183,6,410,273,$FFFFFF)
  		StopDrawing()
  EndIf
EndProcedure

Open_Window_0()
  
Repeat ; Start of the event loop
  
  Event = WaitWindowEvent() ; This line waits until an event is received from Windows
  
  WindowID = EventWindow() ; The Window where the event is generated, can be used in the gadget procedures
  
  GadgetID = EventGadget() ; Is it a gadget event?
  
  EventType = EventType() ; The event type
  
  ;You can place code here, and use the result as parameters for the procedures
  
  
  If Event = #PB_Event_Gadget
    
    If GadgetID = #Button_0
      Gosub Gleichverteilt
      
    ElseIf GadgetID = #String_0
    
    ElseIf GadgetID = #Button_1
      Gosub Zwoelf
    
    ElseIf GadgetID = #Button_2
      Gosub Polar 
      
    ElseIf GadgetID = #Button_3
      Gosub BoxMuller
      
    EndIf
    
  EndIf
  
Until Event = #PB_Event_CloseWindow ; End of the event loop

End

Anzeige:
 Mittel.f= Summe.l/z
  For k=0 To 99
    AbwQSu.f=AbwQSu+((k-Mittel)*(k-Mittel)*Wert(k,0)) ;Aufsummierung Quadrate der Abweichung für "Standardabweichung"
  Next
  StanAbw.f=Sqr(AbwQSu/z)															;Berechnung dewr Standardabweichung
  StartDrawing(WindowOutput(0))
    Box(181,4,413,276,$000000)												;Darstellungsfläche löschen
    Box(183,6,410,273,$FFFFFF)
    For i=0 To 99																			;Darstellungsschleife 1 bis 100
      x= i*4+190																			;Darstellung der Häufigkeit der Zufallszahlen
      y= -Wert(i,0)
      xx=i*4+191
      yy=-Wert(i,1)																		;Darstellung des Idealverlaufes der Häufigkeit
      Line(x,272,0,y)
      Line(xx,272,0,yy,$4A50FC)
    Next
    DrawText(190,10,Bezeichnung$,Farbe)								;Bezeichnung des Verlaufs
  StopDrawing()
  SetGadgetText(#Text_2a,StrF(Mittel,2))							;tatsächl. Mittelwert My eintragen
  SetGadgetText(#Text_3a,StrF(StanAbw.f,2))						;tatsächl. Standartabweichung Sigma eintragen
  SetGadgetText(#Text_5a,Str(Extrem0))								;Anzahl der Werte die kleiner als 1 sind
  SetGadgetText(#Text_6a,Str(Extrem99))								;Anzahl der Werte die größer als 99 sind
  Summe =0																						;Rückstellung der Variblen
  AbwQSu=0
  Extrem0=0
  Extrem99=0
Return

Gleichverteilt:
	;gleichverteilte Zufallszahlen erzeugen 
  Bezeichnung$="gleichverteilte Zufallszahlen"
  Farbe=$F70D08
  z=Val(GetGadgetText(#String_0))											;Anzahl der erzeugten gleichverteilten Zufallszahlen
  DisableGadget(#String_1,1)													;Inaktivschaltung der nichtbenutzten String-Gadgets
  DisableGadget(#String_2,1)
  DisableGadget(#String_3,1)
  For i=0 To 99																			  ;Werte der Feldvariblen auf "Null" setzen
    Wert(i,0)=0
  Next
  
  For i= 1 To z-1																			;z gleichverteilte Zufallszahlen in 100 Kategorien erzeugen
    a=Random(99)
    Wert(a,0)=Wert(a,0)+1															;Zufallswerte in Feldvariable eintragen
    Summe=Summe+a																			;Aufsummierung der erzeugen Zahlen
  Next
  Erw=z/100																						;Theoretische Anzahl pro Zahl berechnen
  For i=0 To 99																				;Werte in Feldvarible einschreiben
    Wert(i,1)=Erw
  Next
  Gosub Genau																					;Genauigkeit der Zufallszahlen berechnen
  Gosub Anzeige																				;Werte anzeigen
Return

Zwoelf:
	;normalverteilte Zufallszahlen nach dem Grenzwertsatz erzeugen, auch als Zwölferregel bekannt. In diesem Verfahren kann
	;auch die Anzahl der gleichverteilten Zufallszahlen je normalverteilte Zufallszahl eingestellt werden. Wird "1" eingegeben,
	;so ist die erzeugte Zufallszahl gleichverteilt. Eine Eingabe von "12" entspricht konkret der Zwölferregel.
  Bezeichnung$="normalverteilte Zufallszahlen, Grenzwertsatz"
  Farbe=$00A000
  z=Val(GetGadgetText(#String_0))											;Anzahl der erzeugten gleichverteilten Zufallszahlen
  mit=Val(GetGadgetText(#String_1))										;Mittelwert My vorgeben
  sta=Val(GetGadgetText(#String_2))										;Standardabweichung Sigma vorgeben
  Anzahl=Val(GetGadgetText(#String_3))								;Aus wievielen Werte soll normalverteilte Zahl errechnet werden?
  DisableGadget(#String_1,0)													;Aktivierung der nötigen String-Gadgets
  DisableGadget(#String_2,0)
  DisableGadget(#String_3,0)
  For i=0 To 99																			  ;Werte der Feldvariblen auf "Null" setzen
    Wert(i,0)=0
  Next
  For i= 0 To z-1																			;Berechnung der "z" normalverteilten Zufallszahlen
    For j= 0 To Anzahl-1															;Erzeugung von "Anzahl" gleichverteilten Zufallszahlen
      b.f= b+Random(99)
    Next
    Faktor.f=8.333/Sqr(Anzahl/12)											;Empirisch gefundene Berechnung auf Standardabweichung=1
    a1.f=((b/Anzahl)-49.5)/Faktor
    a=a1*sta+mit																			;normalverteilte Zufallszahl mit Mittelwert und Standardabweichung
    If a<0
      Extrem0=Extrem0+1																;extreme Werte < Null				Mit dem Grenzwerverfahren erzielt man
    ElseIf a>99																			;														normalverteilte Zahlen, die alle im Bereich
      Extrem99=Extrem99+1													    ;extreme Werte > 99 				der gleichverteilten Zahlen liegen!
    Else
      Wert(a,0)=Wert(a,0)+1														;Werte in Feldvarible schreiben
    EndIf
    Summe.l=Summe+a																		;Aufsummierung der Zufallszahlen
    b=0
  Next
  Gosub Normalverteilung															;Normalverteilungskurve zum Vergleich erzeugen
  Gosub Genau																					;Genauigkeit der Zufallszahlen berechnen
  Gosub Anzeige																				;Werte anzeigen
Return


Polar:
	;normalverteilte Zufallszahlen nach dem Polarverfahren erzeugen. Werte: - bis + unendlich
  Bezeichnung$="normalverteilte Zufallszahlen, Polarmethode"
  Farbe=$00A000
  z=Val(GetGadgetText(#String_0))											;Anzahl der erzeugten gleichverteilten Zufallszahlen
  mit=Val(GetGadgetText(#String_1))										;Mittelwert My vorgeben
  sta=Val(GetGadgetText(#String_2))										;Standardabweichung Sigma vorgeben
  DisableGadget(#String_1,0)													;Aktivierung der nötigen String-Gadgets
  DisableGadget(#String_2,0)
  DisableGadget(#String_3,1)
  For i=0 To 99																			  ;Werte der Feldvariblen auf "Null" setzen
    Wert(i,0)=0
  Next
  
  For i= 1 To z/2-1																		;Berechnung der "z" normalverteilten Zufallszahlen
    Sprung:
      y1.f=(Random(999)+1)/1000												;2 gleichverteilte Zufallszahlen erzeugen
      y2.f=(Random(999)+1)/1000
      q.f=(2*y1-1)*(2*y1-1) + (2*y2-1)*(2*y2-1)
      If q>1
        Goto Sprung																		;Wenn "q.f" > 1, dann zwei neue gleichverteilte Zufallszahlen erzeugen
      EndIf
    p.f=Sqr((-2*Log(q))/q)
    a=(2*y1-1)*p*sta+mit															;2 normalverteilte Zufallszahlen berechnen
    c=(2*y2-1)*p*sta+mit
    If a<0 Or c<0 
      Extrem0=Extrem0+1																;extreme Werte < Null
    ElseIf a>99 Or c>99
      Extrem99=Extrem99+1															;extreme Werte >99
    Else
      Wert(a,0)=Wert(a,0)+1														;Werte a und c in Feldvariable schreiben
      Wert(c,0)=Wert(c,0)+1
    EndIf
    Summe.l=Summe+a+c																	;Aufsummierung der Zufallszahlen
  Next
  Gosub Normalverteilung															;Normalverteilungskurve zum Vergleich erzeugen
  Gosub Genau																					;Genauigkeit der Zufallszahlen berechnen
  Gosub Anzeige																				;Werte anzeigen
Return                                          


BoxMuller:
	;normalverteilte Zufallszahlen nach dem Box-Muller-Algorithmus erzeugen. Werte: - bis + unendlich
  Bezeichnung$="normalverteilte Zufallszahlen, Box-Muller-Algorithmus"
  Farbe=$00A000
  z=Val(GetGadgetText(#String_0))											;Anzahl der erzeugten gleichverteilten Zufallszahlen
  mit=Val(GetGadgetText(#String_1)) 									;Mittelwert My vorgeben
  sta=Val(GetGadgetText(#String_2)) 									;Standardabweichung Sigma vorgeben
  DisableGadget(#String_1,0)        									;Aktivierung der nötigen String-Gadgets
  DisableGadget(#String_2,0)        
  DisableGadget(#String_3,1)
    For i=0 To 99																		  ;Werte der Feldvariblen auf "Null" setzen
      Wert(i,0)=0
    Next
    For i= 1 To z-1
      u1.f=(Random(999)+1)/1000												;2 gleichverteilte Zufallszahlen erzeugen
      u2.f=(Random(999)+1)/1000
      a=Cos(2*3.1416*u1)* Sqr(-2*Log(u2))*Sta+mit			;daraus eine normalverteilte Zufallszahl berechnen
      If a<0
        Extrem0=Extrem0+1															;extreme Werte < Null
      ElseIf a>99           
        Extrem99=Extrem99+1 													;extreme Werte >99
      Else                
        Wert(a,0)=Wert(a,0)+1													;Werte in Feldvarible schreiben
      EndIf
      Summe.l=Summe+a																	;Aufsummierung der Zufallszahlen
    Next
    Gosub Normalverteilung														;Normalverteilungskurve zum Vergleich erzeugen
    Gosub Genau            														;Genauigkeit der Zufallszahlen berechnen
    Gosub Anzeige          														;Werte anzeigen
Return                   


Normalverteilung:
	;Normalverteilungskurve mit vorgegebenen Werten für My und Sigma erzeugen. Vergl. Wikipedia
  For k=0 To 99																				;Werte berechnen Korrekturfaktoren k1.f, h2.f und h3.f sind empirisch
    k1.f=(k-mit)/10																		;ermittelt worden!
    h2.f=z/sta/2.6																		;Höhe der Kurve
    h3.f=50/Pow(sta,2)																;Breite der Kurve
    h.f= h2*Pow(2.7182,-h3*k1*k1)											;Berechnung der 100 Werte
    Wert(k,1)=h																				;Werte für Vergleich in Feldvariable schreiben
  Next
Return


Genau:
;Die Genauigkeit der Verteilung verdoppelt sich ca. mit dem Vierfachen der Anzahl z
	For i=0 To 99
		Gen.l=Gen+Abs(Wert(i,0)-Wert(i,1))								;Abweichungen vom Idealverlauf absolut aufaddieren
	Next
	Prozent.f=Gen*100/z																	;Reative durchscnittliche Abweichung in % berechnen
	SetGadgetText(#Text_10,StrF(Prozent,2))							;Anzeigen der Abweichung
	Gen=0																								;Summierungsvariable auf "Null" setzen
Return

P.S. Habe gerade gesehen, dass der Code nicht im Kasten angezeigt wird. Wie funktioniert das? Berti27

Verfasst: 20.02.2009 21:41
von cxAlex
Ganz toll, aber bitte editiere deinen Code und korregiere die Code - Tags. Du musst

Code: Alles auswählen

 statt [list] verwenden.
Hier gibts noch einen Code zum Thema Zufallszahlen, falls es jemanden interessiert:

http://purebasic-lounge.com/viewtopic.php?t=5726

Verfasst: 20.02.2009 21:55
von Berti27
Habe jetzt [code] statt [list] genommen. Ich glaub ich hab n' Brett vorm Kopf!

Verfasst: 20.02.2009 22:03
von Kaeru Gaman
ich hatte zwischendrin dein posting mal korrigiert, aber du editierst ja schneller und wilder als die Polizei erlaubt! Bild

aktiviere BBCode in deinem Posting und check auch dein Profil, damit es nicht auf "immer deaktiviert" steht. /:->

-----------------------------------------------------------------

hier noch ein Verfahren von mir zum Thema:
http://www.purebasic.fr/german/viewtopi ... 080#203080

Verfasst: 20.02.2009 22:09
von ts-soft
Sieht ja hübsch aus, aber nur solange das Fenster den Desktop nicht verläßt,
ImageGadget wäre die bessere Alternative.

Den Gosub Stil würde ich mir schnellstens abgewöhnen, wir schreiben das
Jahr 2009 ... :mrgreen:

Zu den Zufällen kann ich nichts sagen, da hab ich keine Ahnung von.

Gruß
Thomas

Verfasst: 20.02.2009 22:42
von Berti27
Hallo Kaeru Gaman!
Hab es nun endlich begriffen mit dem BBCode und editiert. :oops: Herzlichen Dank!

Hallo ts-soft!
Nichts für ungut! Du hast ja recht mit dem Code! Aber Gosub war für das einfachste Mittel für 'ne Überprüfung der Abweichungen. Deshalb auch die profane Lösung mit dem Zeichnen auf dem Fenster. Ich werde mal noch dran arbeiten und auf Prozeduren umschreiben. Üben soll ja die Geschicklichkeit erhöhen! :allright: