Seite 1 von 3
RandomQ() - geht doch, sieht aber schlimm aus.
Verfasst: 29.05.2008 12:56
von Kaeru Gaman
OMG
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...)
Verfasst: 29.05.2008 13:27
von rolaf
"Einen Grabstein für den ganzen Schlamassel..."
Wers braucht, mir reicht Random(49) und ein wenig Glück.

Verfasst: 29.05.2008 15:33
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 ^^
Verfasst: 29.05.2008 16:15
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.
Verfasst: 29.05.2008 16:40
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

Verfasst: 29.05.2008 16:56
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!
Verfasst: 29.05.2008 17:46
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

Verfasst: 29.05.2008 17:58
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!
Verfasst: 29.05.2008 18:10
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.
Verfasst: 29.05.2008 18:16
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?
... 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

, das dürfte aber dann wirklich verschmerzbar sein.
MFG PMV