New to Free Basic and have the following question. Is there a way to use the time or date as the seed value for random number generation? Or any way to randomize the result without asking for a seed? Thank you.
Stephen
Ramdom number generation
Re: Ramdom number generation
The most common way to do this is to use the Timer function.
will see the RNG with the results from timer. It is different for different systems.
Or, you could convert the date and time to a double and pass that to Randomize.
Code: Select all
Randomize Timer
Or, you could convert the date and time to a double and pass that to Randomize.
Re: Ramdom number generation
I am sure this will make sense as I learn the code. Please bear with me I have a few small uses for programs to support my game hobby. I used to program on my 8 bit Atari back in the day.
-
- Posts: 4156
- Joined: Jan 02, 2017 0:34
- Location: UK
- Contact:
Re: Ramdom number generation
Firstly, Randomize is sufficient; Timer is implicit.
However, I don't think Timer is useful for seeding purposes.
From the manual: “Note: for all algorithms except algorithm #4, because the fractional part of the seed is clipped, the using the Timer value directly as a parameter will produce the same seed if used more than once in the same second.”
From The manual: “On Windows, the time is measured relative to the point the computer was booted up.”
So if you start your PC every morning, as many do, using Timer as a seed will see a value greater than zero and less than 86,400.
If we query the Timer within the same 30-minute envelope, for example, then the seed range will be within 1800.
If all of the above, then Timer is not the way to go.
Another way is to query the CPU's time stamp counter. This is a 64-bit counter retuned in the registers eax and edx; the lower 32 bits in eax and the upper 32 bits in edx. The counter is not random, obviously, but eax is 'spinning' so fast a query will return an unpredictable value.
If we employ bswap on eax then the byte order is reversed.
This method was mentioned by Steve Hutchesson at the PowerBASIC forum. Steve died a few weeks ago.
The following code describes 'Function GetSeed() As Double'.
In our programs, we simply use 'Randomize GetSeed'.
At the end of the code we print the first Rnd after using 'Randomize GetSeed'. This is for illustration purpose. From the manual: “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, or even possibly worse by inducing sequence overlapping.”
A seed value in the range 0 to '2^32 -1' is returned in just a few hundred nanoseconds.
However, I don't think Timer is useful for seeding purposes.
From the manual: “Note: for all algorithms except algorithm #4, because the fractional part of the seed is clipped, the using the Timer value directly as a parameter will produce the same seed if used more than once in the same second.”
From The manual: “On Windows, the time is measured relative to the point the computer was booted up.”
So if you start your PC every morning, as many do, using Timer as a seed will see a value greater than zero and less than 86,400.
If we query the Timer within the same 30-minute envelope, for example, then the seed range will be within 1800.
If all of the above, then Timer is not the way to go.
Another way is to query the CPU's time stamp counter. This is a 64-bit counter retuned in the registers eax and edx; the lower 32 bits in eax and the upper 32 bits in edx. The counter is not random, obviously, but eax is 'spinning' so fast a query will return an unpredictable value.
If we employ bswap on eax then the byte order is reversed.
This method was mentioned by Steve Hutchesson at the PowerBASIC forum. Steve died a few weeks ago.
The following code describes 'Function GetSeed() As Double'.
In our programs, we simply use 'Randomize GetSeed'.
At the end of the code we print the first Rnd after using 'Randomize GetSeed'. This is for illustration purpose. From the manual: “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, or even possibly worse by inducing sequence overlapping.”
A seed value in the range 0 to '2^32 -1' is returned in just a few hundred nanoseconds.
Code: Select all
Function GetSeed() As Double ' datatype for seed
Dim As ULong Seed
Asm
rdtsc
bswap eax ' fast moving to upper bits
mov Dword Ptr [Seed], eax
End Asm
Return Seed
End Function
For i As ULong = 1 To 10
Print GetSeed
Next
Print
Dim tot As Double
For i As ULong = 1 To 10^8
tot += GetSeed
Next
Print "Average of 10^8:";tot/10^8
Print "Expected value";2^31;" (2^31)"
Print "Ratio";tot/10^8/2^31
Print
For i As ULong = 1 To 10
Randomize GetSeed
Print Rnd
Next
Sleep
-
- Posts: 4156
- Joined: Jan 02, 2017 0:34
- Location: UK
- Contact:
Re: Ramdom number generation
From above "At the end of the code we print the first Rnd after using 'Randomize GetSeed' ". In fact, we execute ten such pairs.
Suppose we executed 10^6 such pairs but totalled the Rnd values instead of printing them. That is:
On one run I got 0.5003335159811867. If we increased the loop to 10^8, taking just less than four minutes on my machine, on one run I got 0.5000163435030816. Clearly, we are 'homing in' on 0.5.
So what does that tell us?
It tells us that even though rdtsc reads a sequential counter, 'Function GetSeed' produces a uniform distribution.
This means a Rnd value of 0.1 or 0.6 or 0.9 or any other value in [0,1) stands the same chance of being the first Rnd after 'Randomize GetSeed' which is precisely what we want; we would rather not see any bias.
Suppose we executed 10^6 such pairs but totalled the Rnd values instead of printing them. That is:
Code: Select all
Dim tot As Double
For i As ULong = 1 To 10^6
Randomize GetSeed
tot += Rnd
Next
Print tot/10^6
So what does that tell us?
It tells us that even though rdtsc reads a sequential counter, 'Function GetSeed' produces a uniform distribution.
This means a Rnd value of 0.1 or 0.6 or 0.9 or any other value in [0,1) stands the same chance of being the first Rnd after 'Randomize GetSeed' which is precisely what we want; we would rather not see any bias.