lundi 28 janvier 2019

Randomize seems to miss many possible seeds

I wrote the following in an attempt to implement the Box-Muller transform to generate random normal variables in pure VBA:

Function RandNorm(Optional mean As Double = 0, Optional sd As Double = 1) As Double
    Dim s As Double
    s = Sqr(-2 * Log(Rnd())) * Cos(6.283185307 * Rnd()) '6.28 etc. is 2*pi
    RandNorm = mean + sd * s
End Function

The following somewhat weak test always works, returning a number close to 0:

Sub test1()
    Randomize
    Dim s As Double
    Dim i As Long
    For i = 1 To 17000000
        s = s + RandNorm()
    Next i
    Debug.Print s / 17000000 
End Sub

On the other hand, the following test never works (because it tries to take the log of 0, which is undefined):

Sub test2()
    Randomize
    Dim s As Double
    Dim i As Long
    Debug.Print Rnd() 'just to clock it
    For i = 1 To 17000000
        s = s + RandNorm()
    Next i
    Debug.Print s / 17000000   
End Sub

The problem is that rnd() returns 0 on average once out of every 2^24 (a bit less than 17,000,000) calls. It is of course easy enough to tweak the definition of RandNorm to avoid the zero, but I am still puzzled by the above code. It would make perfect sense to me if each test failed half the time (when the zero is fed into Log()) and worked half the time (when the zero is fed into Cos()). It seems that Randomize avoids at least half of the possible seeds.

Is there a way to seed the random number generator so that each test fails half the time?




Aucun commentaire:

Enregistrer un commentaire