Here is a suggestion for independent function. It doesn't work exactly the same, but I paid a lot attention to details on how it works.
Code:
Public Function RndM(Optional ByVal Number As Long) As Double
Static lngX As Long, lngY As Long, lngZ As Long, blnInit As Boolean
Dim dblRnd As Double
' if initialized and no input number given
If blnInit And Number = 0 Then
' lngX, lngY and lngZ will never be 0
lngX = (171 * lngX) Mod 30269
lngY = (172 * lngY) Mod 30307
lngZ = (170 * lngZ) Mod 30323
Else
' if no initialization, use Timer, otherwise ensure positive Number
If Number = 0 Then Number = Timer * 60 Else Number = Number And &H7FFFFFFF
lngX = (Number Mod 30269)
lngY = (Number Mod 30307)
lngZ = (Number Mod 30323)
' lngX, lngY and lngZ must be bigger than 0
If lngX > 0 Then Else lngX = 171
If lngY > 0 Then Else lngY = 172
If lngZ > 0 Then Else lngZ = 170
' mark initialization state
blnInit = True
End If
' generate a random number
dblRnd = CDbl(lngX) / 30269# + CDbl(lngY) / 30307# + CDbl(lngZ) / 30323#
' return a value between 0 and 1
RndM = dblRnd - Int(dblRnd)
End Function
Here are a few pointers:- True conditions are faster than False conditions -> set code that is ran more often behind True condition.
- I minimized the amount of calculation when checking for initialized values. By using a local static variable we know that X, Y and Z are valid.
- I decided to use 0 as number to cause Timer to be used automatically for seeding: if someone wants repeatable random numbers, he knows to give a seed.
- ... which leads to this function having an advantage over Rnd as you don't need to call Randomize to get a different set of random numbers on each run of the application.
- And I used variable names that tell better what datatype they represent.