RandomQ() - geht doch, sieht aber schlimm aus.

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

RandomQ() - geht doch, sieht aber schlimm aus.

Beitrag von Kaeru Gaman »

OMG :shock:

Code: Alles auswählen

Procedure.q RandomQ( RangeH.q )
Protected ResultH.q
Protected ResultM.q
Protected ResultL.q
Protected RangeM.q
Protected RangeL.q
Protected Sign.q = 1

  If RangeH < 0
    RangeH = -RangeH
    Sign = -1
  EndIf

  If RangeH > 2147483647
    RangeL = RangeH & $FFFF
    RangeM = ( RangeH & $FFFF0000 ) >> 16
    RangeH >> 32
    ResultH = Random( RangeH )
    If ResultH = RangeH
      ResultM = Random( RangeM )
      If ResultM = RangeM
        ResultL = Random( RangeL )
      Else
        ResultL = Random( $FFFF )
      EndIf
    Else
      ResultM = Random( $FFFF )
      ResultL = Random( $FFFF )
    EndIf
    ResultH = (ResultH << 32) + (ResultM << 16) + ResultL
  Else
    ResultH = Random( RangeH )
  EndIf

  ResultH * Sign

ProcedureReturn ResultH
EndProcedure
habs jetzt nicht auf Herz und Nieren getestet, müßte aber so richtig sein, außer die Quads machen noch Probleme....
(und außer ich hab nen blöden typo irgendwo übersehen...)
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
rolaf
Beiträge: 3843
Registriert: 10.03.2005 14:01

Beitrag von rolaf »

"Einen Grabstein für den ganzen Schlamassel..." :lol:

Wers braucht, mir reicht Random(49) und ein wenig Glück. :mrgreen:
:::: WIN 10 :: PB 5.73 :: (x64) ::::
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7032
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Beitrag von STARGÅTE »

gut scheint schon mal unbaggiger zu sein als das andere..

trotzdem bereiten mit deine vielen Abfragen sorge.
Stichwort: Bedingte Wahrscheinlichkeit
Denn vllt hast du dadurch einer gruppe von Zahlen eine kleinere Wahrscheinlichkeit gegeben zu kommen, aber normal.

Ich kanns ehrlichgesagt nicht beurteilen, da ich nicht genau weiß was du da machst ^^
Aber sowas ist sehr gefährlich (in bezug auf die unbedingte Wahrscheinlichkeit):

Code: Alles auswählen

      ResultM = Random( RangeM ) 
      If ResultM = RangeM 
        ResultL = Random( RangeL ) 
      Else 
        ResultL = Random( $FFFF ) 
      EndIf 
klar ist Random, eh schon bedingt duch die berechnung mit hilfe der internen zeit, aber trotzem.

Ich werde das noch mal ausgiebiger testen, bis in 4 Jahren dann ^^
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

mit der verteilung könntest du recht haben, die ist ursprünglich recht gleichmäßig.
inwieweit das durch den mehrfachen aufruf geschädigt wird, ist eben die frage,
weil ich nunmal drei randoms brauche, um ein Quad zu erzeugen.

erklärung:
ich kann das untere LONG nicht mit einem einzigen Random erzeugen,
weil die ausgabe nur positiv ist, also kann niemals das höchste bit gesetzt sein.
deswegen zerlege ich das untere LONG in HiWord und LoWord, und erzeuge das getrennt.

die zusätzlichen IFs sind für die grenzfälle:
wenn das obere Long an die obere Grenze stößt,
dann dürfen die weniger signifikanten stellen auch nur bis an die grenze gehen.
wenn nicht, müssen die unteren Words komplett gefüllt werden können.

ich demonstrier das mal anhand einer dezimalzahl, das ist einfacher zu verstehen:

nehmen wir mal an, eine dezimalzahl würde in dreistelligen einheiten gespeichert werden.
jetzt will ich eine zufallszahl mit dem Range 12.345.678 erzeugen.

wenn ich als ergebnis oben eine 10 habe, dürfen die folgenden stellen 000-999 sein.
wenn ich aber eine 12 bekommen hab, darf ich nur 000-345 erzeugen, um im Range zu bleiben.
zusätzlich, wenn ich dann auch noch 345 erzeugt hab, dürfen die untersten stellen nur 678 werden.

das mache ich durch die IFs in meiner Proc:
wenn ich den Range erreiche, dürfen die niederen stellen nur bis zu deren Range gehen,
ansonsten müssen sie bis $FFFF gehen können.
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Andreas_S
Beiträge: 787
Registriert: 14.04.2007 16:48
Wohnort: Wien Umgebung
Kontaktdaten:

Beitrag von Andreas_S »

hier vil. eins für 2er Exponenten:

Code: Alles auswählen

Procedure RandomQ(bits)
	bits - 1
	result.q
	
	For i = 0 To bits
		result + Random(1) << i
	Next
	
	ProcedureReturn result
EndProcedure
weis aber nicht ob das so sinnvoll ist...

RSBasic hat geschrieben:@Franky
Super Code :lol: :lol: :lol:
/:->
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7032
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Beitrag von STARGÅTE »

OK, habs verstenden Kaeru Gaman,

muss dir aber genau deswegen leider sagen das du damit keine gleich verteilung erreichst.

Um dein Beispiel zu benutzen:
nehmen wir mal an wir wollen eine Zufallszahl im Bereich 3.001

Dann erzeugst du erst eine Zuallszahl von 0 bis 3 (welche dann verschoben wird) und danach entweder eine Random(999) oder eine Random(1)
und genau dort liegt leider der Fehler, denn mit der ersten Zufallszahl teilst du die Zahlen in 4 blöcke:
0-999, 1000-1999, 2000-2999, 3000-3999
dummerweise darf es aber keine zahlen über 3001 gehen, also wird der hintere Block geschrumpft.
Also tritt dort ein ungleichgewicht auf:
die Zahlen 3000 oder 3001 kommen ca 500 mal häufiger als alle anderen zahlen.

Ob das nun schlimm ist, sollte jeder selber entscheiden.

Für sensible Programme die auf die gleichverteilung setzten wäre das jedoch tödlich!
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
marco2007
Beiträge: 906
Registriert: 26.10.2006 13:19
Kontaktdaten:

Beitrag von marco2007 »

Hi,

meine Variante ist zwar etwas primitiver, aber spricht etwas dagegen?
Eine Zahl kann auch aus lauter Zufallsziffern bestehen, oder?

Code: Alles auswählen

For i=0 To 99999999
a.s=Str(Random(9))+Str(Random(9))+Str(Random(9))+Str(Random(9))+Str(Random(9))+Str(Random(9))+Str(Random(9))+Str(Random(9))
  If Val(a)<100
    Debug ValQ(a)
  EndIf
Next
lg
Marco

PS: Schön und schnell ist`s natürlich nicht und verglichen mit dem Code von KG, wirkt das etwas erbärmlich :oops:
Windows 11 - PB 6.03 x64
_________________________________
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7032
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Beitrag von STARGÅTE »

da spricht nix dagegen.

allerdingst verschinkt es enorm viel Zeit, erst eine 9999... Zufallszahl zu erzeugen (was ja ok ist, da die Blöcke gleich größ sind) aber dann zu sortieren ob die Zahl innerhalb der Grenzen ist.

Sauber wäre das dann so ok:

Code: Alles auswählen

Procedure RandomQ(Quad.q) 
 Length = Len(StrQ(Quad))
 Repeat
  Zahl$ = ""
  For n = 1 To Length
   Zahl$ + Str(Random(9))
  Next n
 Until ValQ(Zahl$)<=Quad
 ProcedureReturn ValQ(Zahl$)
EndProcedure
Allerdings sehr Zeitraubend!
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

gute argumentation mit der verteilung...

aber ich hab mal wieder den wald vor lauter bäumen nicht gesehen...

62bit zufallszahlen kann man ganz bequem so erzeugen:

Code: Alles auswählen

Procedure.q RandomQ( Range.q )
Protected Result.q

  If Range > $7FFFFFFF
    Repeat
      Result = ( Random($7FFFFFFF) << 31 ) + Random($7FFFFFFF)
    Until Result <= Range
  Else
    Result = Random( Range )
  EndIf

ProcedureReturn Result
EndProcedure
hierbei verzichte ich bei der Quad auf die beiden obersten bits,
damit mache ich die 31bit-einschränkung von Random wieder wett.
dafür haben wir hier wirklich ne saubere verteilung.
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
PMV
Beiträge: 2765
Registriert: 29.08.2004 13:59
Wohnort: Baden-Württemberg

Beitrag von PMV »

Einfach ... aber das Repeat wird ja so lang ausgeführt, bis mal ein
Ergebnis kleiner ist als die größte erlaubte Zahl ... kann hier jemand
Wahrscheinlichkeitsrechnung? :mrgreen:

... bei "kleineren" Quad-Zahlen wird da sicher einiges an Rechenleistung
verbraten.

Ich würd empfehlen, der einzige einwand war ja die ungerechte Verteilung,
dass genau das Problem behoben wird. Also die zwei Randoms auf die
gleiche Anzahl Bits verteilen ... auch wenns für ungerade Zahlen schwirig
wird :lol:, das dürfte aber dann wirklich verschmerzbar sein.

MFG PMV
alte Projekte:
TSE, CWL, Chatsystem, GameMaker, AI-Game DLL, Fileparser, usw. -.-
Antworten