Richard
Mon Sep 18 22:18:11 CDT 2006
"Dr John Stockton" <jrs@merlyn.demon.co.uk> wrote in message
news:3YwxaSAlDxDFFwAg@merlyn.demon.co.uk...
> JRS: In article <ukNHkjg2GHA.1040@TK2MSFTNGP06.phx.gbl>, dated Sat, 16
> Sep 2006 22:25:11 remote, seen in news:microsoft.public.scripting.vbscri
> pt, Richard Mueller <rlmueller-NOSPAM@ameritech.NOSPAM.net> posted :
...
>>
>>Documentation says that Randomize seeds the Rnd function with a value from
>>the Timer function. The Timer function returns the number of seconds since
>>midnight, to the nearest 100th of a second. The values range from 0.00 to
>>86400.00, so 8,640,000 values.
>
> You mean 86399.99, 8,639,999.
>
Yes.
> No, the Timer returns the number of seconds, reported as a multiple of
> 0.01 seconds. It does not necessarily change every 0.01 seconds; in my
> system it updates at 18.2 Hz, so takes steps of 5 or 6 in the second
> decimal place. In other systems it does update faster.
>
I expected the same, since the system timer ticks 18.2065 times per second.
Before I posted I tested on a Pentium 3 system and found that the output
incremented in 0.01 seconds. However, the OS was w2k. I also tested on an XP
system. After your posting I tested again on an identical Pentium 3, but
with Win98, and Timer incremented in larger intervals. Same on a Pentium 4
with Win98. Interesting.
>
>>Rnd itself is said to be a 24-bit Linear Congruential Generator of maximal
>>length, so it can generate 16,777,216 (2^24) different values. However,
>>only
>>7 digits are displayed.
>
> Rnd surely generates an IEEE Double, capable of 53 bit resolution but in
> this case presumably using only 24. It is conversion-to-string which
> gives values with 7 or fewer decimal places or in E-format. I see, for
> example,
> 0.7747401
> 1.401764E-02
> 0.7607236
> 0.81449
> 0.7090379
>
> Try
> document.write "<pre>"
> for K = 1 to 50
> R = Rnd
> document.write R, " ", R*16777216, "<br>"
> next
> document.write "</pre>"
> to see that the results of Rnd do effectively have 24 significant bits.
>
I find that Rnd * 16777216 is always an exact integer.
>
> To be sure of getting equi-probable digits, one must either use Rnd as a
> number in 0..1 or, if going via string, think rather carefully.
>
>
> Also disappointing, since it has for many years been very practical to
> use a generator with 32 bits. ISTR that Turbo Pascal had such in the
> late 1980s.
>
> If the application needs good Randoms, one can use javascript, or write
> one's own - follow Knuth or my pas-rand.htm
It seems that VB and VBScript are limited to 15 decimal digits. I think that
is why they limit the LCG to 24 bits. I agree this is disappointing. In
assembly it is straightforward to create a 64-bit LCG, even using 32-bit
registers. Years ago I created a psuedo random number generator in assembly
with a period of about 2^222 (in theory at least, based on Knuth).
I find the Rnd function is equivalent to the following function, divided by
16777216 and rounded to 7 digits. In the snippet below I do not round the
output of my function to 7 digits:
=============
' Constants for Linear Congruential Generator.
Const A = 16598013
Const C = 12820163
Const M = 16777216
' Initialize with any seed.
' x is series created by Rnd.
' y is series created by Function LCG.
Randomize(.5)
x = Rnd
y = x * M
' Output next 50 numbers from each.
For = 1 To 50
x = Rnd
y = LCG(y)
Wscript.Echo x & ", " y / M
Next
Function LCG(lngSeed)
LCG = A * lngSeed
LCG = LCG + C
LCG = LCG / M
LCG = (LCG - Fix(LCG)) * M
End Function
=========
My function LCG must use the integers or it won't work. Rounding to 7 digits
after dividing by M is not easy. For example, 0.008614659 is not rounded to
0.0086147.
I have not figured out what the Randomize function does. It accepts any
number you give it. I have not been able to find a value to pass to
Randomize that duplicates what it does when you do not pass a value to it.
For example, Randomize(Timer) is not equivalent to Randomize().
--
Richard
Microsoft MVP Scripting and ADSI
Hilltop Lab -
http://www.rlmueller.net