freak wrote:
A tip: If you use Random() with the unsigned maximum for an integer type (so $FFFFFFFF on x86, $FFFFFFFFFFFFFFFF on x64) then even this multiplication step is skipped and you get plain 32 or 64 pseudo-random bits which actually gives you better statistical properties
Holy cow freak, that is kickass.
Wait a sec, that means I could just do a:
Code:
Define.i num,i
For i=1 To 100
num=Random($FFFFFFFFFFFFFFFF)
Debug num&$1 ;get LSB
Next
To get coin toss.
And for larger numbers, all I would need to do is change the mask to get the "n" number of LSB's...
Hang on, would using a bitmask be a speedier way to return the result than Random() currently does? (it could then always use the max 64bits internally, and remove that multiplication step)
@idle: you might like this test example. Note! the entropy comments are as seen on my system, yours might vary. I got 1.0 most of the time, and once in a while 0.99
Although with freak revealing the "trick", combined with bitmasking the result to get the random bits/bytes you want, for potential speed reasons alone I'm leaning towards Random() now though. (haven't done speed comparison tests yet on RandomBit() and Random(), RandomBit() must be 64 times faster than Random() to actually have a speed gain. ugh)
Code:
EnableExplicit
DisableDebugger
Procedure.i RandomByte()
!XOR ECX,ECX ;Set ECX to 0.
!RDTSC ;get TSC (and put it in EDX:EAX, we only want the LSB in EAX though)
!AND EAX,$1 ;discard all but the LSB in EAX (and put the result in EAX)
!OR ECX,EAX ;OR EAX with ECX to build our bit collection
!RDTSC
!AND EAX,$1
!SHL EAX,1 ;shift the bit to the left in preparation for the OR
!OR ECX,EAX
;All this should probably be turned into a loop for speed and scalability (1 to 64bit).
;Any ASM gurus wanna give a tight loop a try?
!RDTSC
!AND EAX,$1
!SHL EAX,2
!OR ECX,EAX
!RDTSC
!AND EAX,$1
!SHL EAX,3
!OR ECX,EAX
!RDTSC
!AND EAX,$1
!SHL EAX,4
!OR ECX,EAX
!RDTSC
!AND EAX,$1
!SHL EAX,5
!OR ECX,EAX
!RDTSC
!AND EAX,$1
!SHL EAX,6
!OR ECX,EAX
!RDTSC
!AND EAX,$1
!SHL EAX,7
!OR ECX,EAX
!MOV EAX,ECX ;copy our bit collection to EAX
ProcedureReturn ;return EAX
EndProcedure
EnableDebugger
Define.i i,sum,num
Define.d calc
sum=0
For i=1 To 100;0000
num=RandomByte()+1 ;we want 1-256 in this case and not 0-255 which it really returns.
sum+num
;Debug RSet(Bin(num,#PB_Byte),8,"0")
;Debug num
Next
calc=(i*128)/sum ;calculate the summed spread.
Debug StrD(calc,2)
;If result is 1.0 this equals perfect entropy,
;you'll most likely see it showing 0.99,1.0,1.01 if you run this test multiple times,
;so it's not perfect, it all depends on number of loops and
;rounding errors of the float math used to calculate the sum,
;and the actual entropy as well.
;There is no rounding issues with RandomByte() obviously as it's integer.