FB RANDOMIZE() and RND() seed parameters ignore the mantissa

General FreeBASIC programming questions.
cbruce
Posts: 163
Joined: Sep 12, 2007 19:13
Location: Dallas, Texas

FB RANDOMIZE() and RND() seed parameters ignore the mantissa

Post by cbruce »

Took me a while to figure out what was screwing up what I thought was some very simple code... (maybe needs a documentation addition?)

Although Randomize() takes a DOUBLE for a seed parm and RND() takes a SINGLE for a seed parm, any mantissa on those values is ignored. Only the INTEGER portion of the seed value is utilized:

Code: Select all

'------
randomize ((0.0), 3)
print rnd()
randomize ((0.492385749), 3)
print rnd()
randomize ((0.209870021), 3)
print rnd()
randomize ((567.834238348), 3)
print rnd()
randomize ((567.763782781), 3)
print rnd()
randomize ((567.129834667), 3)
print rnd()
'------
' 0.3300995409954339
' 0.3300995409954339
' 0.3300995409954339
' 0.1059813974425197
' 0.1059813974425197
' 0.1059813974425197
'------
deltarho[1859]
Posts: 4292
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: FB RANDOMIZE() and RND() seed parameters ignore the mantissa

Post by deltarho[1859] »

From Help:
"Note: using the Timer value directly as a parameter will produce the same seed if used more than once in the same second."

Is that telling us the 'mantissa' is ignored?
cbruce wrote:(maybe needs a documentation addition?)
Yes. Image
deltarho[1859]
Posts: 4292
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: FB RANDOMIZE() and RND() seed parameters ignore the mantissa

Post by deltarho[1859] »

I checked the fbc source and cbruce's suspicions are confirmed except for generator #4 (QBASIC) which does not clip the seed to an integer. Image
fxm
Moderator
Posts: 12083
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: FB RANDOMIZE() and RND() seed parameters ignore the mantissa

Post by fxm »

From Manual:
When you call Randomize with the QB compatible algorithm, part of the old seed is retained. This means that if you call Randomize several times with the same seed, you will not get the same sequence each time. To get a specific sequence in QB compatible mode, set the seed by calling Rnd with a negative parameter.
jj2007
Posts: 2326
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: FB RANDOMIZE() and RND() seed parameters ignore the mantissa

Post by jj2007 »

deltarho[1859] wrote:Yes. Image
Absolutely. Preferably a less cryptic one.
deltarho[1859]
Posts: 4292
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: FB RANDOMIZE() and RND() seed parameters ignore the mantissa

Post by deltarho[1859] »

With Timer we are limited to a integral seed between 0 and 86399; 86400 seconds per day. *

If we use Randomize Timer*10^9 we utilize Timer down to a nanosecond.

eg Timer As Double => 50400.12345678943
Int( Timer*10^9 ) => 50400123456789

Randomize Timer*10^9
Print Rnd
Randomize Timer*10^9
Print Rnd
Randomize Timer*10^9
Print Rnd

'------
0.4776034094393253
0.704629176761955
0.7251559856813401
'------

Added: We could put that tip in the docs. Image

* That isn't true - I'm thinking of PB's Timer which rolls over at midnight. FB is linked to the Performance Counter - but an integral value of seconds is still used.
deltarho[1859]
Posts: 4292
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: FB RANDOMIZE() and RND() seed parameters ignore the mantissa

Post by deltarho[1859] »

cbruce wrote:Only the INTEGER portion of the seed value is utilized:
and only 32 bits of that.

Code: Select all

Dim As Ulong L1, L2
' By MrSwiss
Sub GetUlongs( n As Ulongint, ByRef L1 As Ulong, ByRef L2 As ulong)
  L1=Cast( Ulong Ptr, @n )[0]
  L2=Cast( Ulong Ptr, @n )[1]
End Sub

Randomize 2^54+58143
Print Rnd

GetUlongs(2^54+58143, L1, L2)
Randomize L1
Print Rnd 
Sleep
'------
0.9612885063979775
0.9612885063979775
'------
So instead of Timer we can simply use a 32-bit random number and there are lots of ways of doing that. We are limited then to a value of [0,2^32-1]. I am not impressed.
Last edited by deltarho[1859] on Jun 02, 2021 3:34, edited 1 time in total.
deltarho[1859]
Posts: 4292
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: FB RANDOMIZE() and RND() seed parameters ignore the mantissa

Post by deltarho[1859] »

Intel's RdRand has been around for 9 years so if you have that on board you can use this:

Code: Select all

Dim As Ulong Seed
Asm
  RdRand eax
  mov Dword Ptr [Seed], eax
End Asm
Randomize Seed
Print Rnd
Sleep
fxm
Moderator
Posts: 12083
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: FB RANDOMIZE() and RND() seed parameters ignore the mantissa

Post by fxm »

The difference between the following 2 examples is explained by taking into account the fact that the passed argument (as 'seed' to 'Randomize()') is first casted to a Double before being then casted to a Ulong:

Code: Select all

Dim As Ulong L1A, L2A, L1B, L2B

Sub GetUlongs( ByVal n As Ulongint, ByRef L1 As Ulong, ByRef L2 As ulong)
  L1=Cast( Ulong Ptr, @n )[0]
  L2=Cast( Ulong Ptr, @n )[1]
End Sub

Randomize 2^54+58143
Print Rnd

GetUlongs(2^54+58143, L1A, L2A)
Randomize L1A
Print Rnd

Print

Randomize (1ull Shl 54)+58143
Print Rnd

GetUlongs((1ull Shl 54)+58143, L1B, L2B)
Randomize L1B
Print Rnd

'------
' 0.9612885063979775
' 0.9612885063979775
'
' 0.9612885063979775
' 0.4379609904717654
'------

Print
Print Cast(Ulong, 2^54+58143), Cast(Ulong, Cast(Double, 2^54+58143))
Print Cast(Ulong, L1A), Cast(Ulong, Cast(Double, L1A))
Print
Print Cast(Ulong, (1ull Shl 54)+58143), Cast(Ulong, Cast(Double, (1ull Shl 54)+58143))
Print Cast(Ulong, L1B), Cast(Ulong, Cast(Double, L1B))

'------
'58144         58144
'58144         58144
'
'58143         58144
'58143         58143
'------

Sleep
deltarho[1859]
Posts: 4292
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: FB RANDOMIZE() and RND() seed parameters ignore the mantissa

Post by deltarho[1859] »

OK. I think that the secret is to supply a 32 bit seed and leave it at that.

For Windows, if RdRand is not available, here is another way:

Code: Select all

Declare Function RtlGenRandom Lib "Advapi32.dll" Alias "SystemFunction036" _
  ( RandomBuffer As Any Ptr, RandomBufferLength As Ulong ) As Byte 
Dim As Ulong Seed
RtlGenRandom( @Seed, 4 )
Randomize Seed
Print Rnd
Sleep
This is similar to CryptGenRandom but we don't have to invoke a Cryptographic Service Provider.
fxm
Moderator
Posts: 12083
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: FB RANDOMIZE() and RND() seed parameters ignore the mantissa

Post by fxm »

deltarho[1859] wrote:OK. I think that the secret is to supply a 32 bit seed and leave it at that.
Yes, so the pre-cast to a Double will never change the final Ulong value.
deltarho[1859]
Posts: 4292
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: FB RANDOMIZE() and RND() seed parameters ignore the mantissa

Post by deltarho[1859] »

Here is another way which will work on Windows and Linux:

Code: Select all

' Adapted from MrSwiss
Function GetSeed() As Ulong
  Dim As Ulong i, res
  Randomize , 5     ' Crypto
  For i = 0 to 3
    Cast( Byte Ptr, @res )[i] = Rnd*256
  Next
  Return res
End Function

Randomize GetSeed, 3   ' Mersenne Twister, for example
Print Rnd
Sleep 
It is a good job we should only use Randomize once in an application session because GetSeed takes a while on my machine - 8 milliseconds. Image
fxm
Moderator
Posts: 12083
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: FB RANDOMIZE() and RND() seed parameters ignore the mantissa

Post by fxm »

deltarho[1859] wrote:
cbruce wrote:(maybe needs a documentation addition?)
Yes. Image
I don't know if a documention complement is absolutely necessary, but if so I would suggest one like this:
.....
Note: using the Timer value directly as a parameter will produce the same seed if used more than once in the same second. However, it is generally not worth calling Randomize twice with unpredictable seeds anyway, because the second sequence will be no more random than the first. In most cases, the Mersenne twister should provide a sufficiently random sequence of numbers, without requiring reseeding between Rnd calls.
More generally, after the Randomize call copies the user seed argument (passed by value) into a local Double variable, the result is then casted to Ulong before use.
.....
Last edited by fxm on Jun 02, 2021 17:58, edited 1 time in total.
Reason: very slightly reworded the proposed addition sentence
deltarho[1859]
Posts: 4292
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: FB RANDOMIZE() and RND() seed parameters ignore the mantissa

Post by deltarho[1859] »

fxm wrote:More generally, after a copy of the user seed argument (passed by value) into a local Double variable, the result is then casted to a Ulong before use.
I shouldn't think that most users would be interested in what is happening internally and may think, after reading that, "So what?".

Using Timer shortly after a system restart is not a good idea and why the better option is to use a random Ulong.

The bad thing about using Randomize more than once is the possibility of overlapping sequences.
Imortis
Moderator
Posts: 1923
Joined: Jun 02, 2005 15:10
Location: USA
Contact:

Re: FB RANDOMIZE() and RND() seed parameters ignore the mantissa

Post by Imortis »

deltarho[1859] wrote:
fxm wrote:More generally, after a copy of the user seed argument (passed by value) into a local Double variable, the result is then casted to a Ulong before use.
I shouldn't think that most users would be interested in what is happening internally and may think, after reading that, "So what?".

Using Timer shortly after a system restart is not a good idea and why the better option is to use a random Ulong.

The bad thing about using Randomize more than once is the possibility of overlapping sequences.
The "so what" is pretty obvious to me. If a float is cast to an integer before use, the mantissa goes away and is unimportant to the process. If you know what a double is, and you know what a ulong is, and you know what a cast is, then there is no question what that means.

I think it is a good addition. I did not know before this that the mantissa was ignored in Randomize. I think it is good to have it listed as above.
Post Reply