Looking for a random number generator, I've found (thanks to one of my "C++ pals") a routine which could be expanded to assembly as:
It seems to produce well-distribued random dwords and I'm used to initialize the seed with RDTSC. That's all for the integers. Now to the floating point results.
The easiest way to produce a random floating point value I've managed to write on my own is:
This procedure provides (just as the integer one) a very good distribution of values, however:
- resulting values are in the range between 1.0 (inclusive) and 2.0 (exclusive), and I've not found any reasonable integer method for range conversion (any ideas?)
- results are returned in EAX, not on the top of FPU's stack. That seems to be against the "common" rules, but can be easily used for purposes of:
Alternatively, I'd propose such a modification (this solves both oddities listed above):
Cheers, Mikael
iRand PROC USES EDX
mov EAX,00BB38435h
mul
add EAX,03619636Bh
mov ,EAX
ret
iRand ENDP
It seems to produce well-distribued random dwords and I'm used to initialize the seed with RDTSC. That's all for the integers. Now to the floating point results.
The easiest way to produce a random floating point value I've managed to write on my own is:
fRand PROC USES EDX
mov EAX,00BB38435h
mul
add EAX,03619636Bh
mov ,EAX
and EAX,07FFFFFFFh ; get rid of sign bit
or EAX,03F800000h ; fix the exponent
ret
fRand ENDP
This procedure provides (just as the integer one) a very good distribution of values, however:
- resulting values are in the range between 1.0 (inclusive) and 2.0 (exclusive), and I've not found any reasonable integer method for range conversion (any ideas?)
- results are returned in EAX, not on the top of FPU's stack. That seems to be against the "common" rules, but can be easily used for purposes of:
mov ,$INVOKE(fRand)
Alternatively, I'd propose such a modification (this solves both oddities listed above):
fRand PROC
push EAX
push EDX
fld1
mov EAX,00BB38435h
mul
fadd st(0),st(0)
add EAX,03619636Bh
mov ,EAX
and EAX,07FFFFFFFh ; get rid of sign bit
or EAX,03F800000h ; fix the exponent
xchg EAX,
pop EDX
fsub DWORD PTR
add ESP,04
ret
fRand ENDP
Cheers, Mikael
There seems to be one more oddity with your algo for floating point values:
Based on random distribution of bits, bit30 should be set some 50% of the time. This means that the generated float value would be considered as a NAN some 50% of the time if you tried to use it as a parameter on the FPU. I do agree that the other 50% of the time, the generated number would be between 1 and 2.
A result between 0 and 1 would be more acceptable since it could easily be converted to a random value within a specified range. My suggestion to prevent NANs and provide a random fractional floating point number between 0 and 1 would be (still based on your RNG algo):
Raymond
Based on random distribution of bits, bit30 should be set some 50% of the time. This means that the generated float value would be considered as a NAN some 50% of the time if you tried to use it as a parameter on the FPU. I do agree that the other 50% of the time, the generated number would be between 1 and 2.
A result between 0 and 1 would be more acceptable since it could easily be converted to a random value within a specified range. My suggestion to prevent NANs and provide a random fractional floating point number between 0 and 1 would be (still based on your RNG algo):
mov eax,00BB38435h
mul
add eax,03619636Bh
mov ,EAX
and eax,3FFFFFFFh ;instead of 7FFFFFFFh
or eax,3F800000h ; fix the exponent to 1
push eax
fld dword ptr
fld1
fsubp st(1),st
pop eax ;clean stack
Raymond
You're absolutely right. Since we need an exponent equal to 127, bit 30 should be always cleared and thus - we need to and EAX with 3FFFFFFFh. Thanks.