Here is the VBA code for a class (which I call CVirtTime) that performs random number generation using a "virtual clock" that is not affected by the speed of the computer running the code. This virtual clock will advance the virtual time each time you call method NextRand() which generates uniform random numbers between 0 and 1. You must initialize the instance of the class using either InitMyTime or InitTime. The first method allows you to specify any time and date you want (and therefore you can duplicate the sequence of numbers generated). The method InitTime initializes the class instance using the current system date and time. Using this method you cannot replicate the sequence of random numbers. Once you initialize the class instance the virtual clock "ticks" as fast as the number of calls to method NextRand().

Option Explicit
Private m_nSec As Integer

Private m_nMin As Integer

Private m_nHour As Integer

Private m_nDay As Integer

Private m_nMonth As Integer

Private m_nYear As Integer

Private m_fCounter As Double

Private PI As Double

Private Function Log10(ByVal X As Double) As Double

Log10 = Log(X) / Log(10)

End Function

Private Function AbSin(ByVal X As Double) As Double

AbSin = Abs(Sin(X)) + 1

End Function

Private Function AbCos(ByVal X As Double) As Double

AbCos = Abs(Cos(X)) + 1

End Function

Private Sub INC(ByRef N As Integer)

N = N + 1

End Sub

Public Sub InitMyTime(ByVal nSec As Integer, ByVal nMin As Integer, ByVal nHour As Integer, _

ByVal nDay As Integer, ByVal nMonth As Integer, ByVal nYear As Integer)

m_nSec = Abs(nSec)

If m_nSec > 59 Then m_nSec = 0

m_nHour = Abs(nHour)

If m_nHour > 23 Then m_nHour = 0

m_nMin = Abs(nMin)

If m_nMin > 59 Then m_nHour = 0

m_nDay = Abs(nDay)

If m_nDay > 30 Or m_nDay = 0 Then m_nDay = 1

m_nMonth = Abs(nMonth)

If m_nMonth > 12 Or m_nMonth = 0 Then m_nMonth = 1

m_nYear = Abs(nYear)

If m_nYear < 1900 Then m_nYear = 1900

m_fCounter = 0

PI = 4 * Atn(1)

End Sub

Public Sub InitTime()

Dim t As Date

t = Now

m_nSec = Second(t)

m_nHour = Hour(t)

m_nMin = Minute(t)

m_nDay = Day(t)

m_nMonth = Month(t)

m_nYear = Year(t)

m_fCounter = 0

PI = 4 * Atn(1)

End Sub

Public Function NextRand() As Double

Dim X As Double

' manage the virtual time and date

If m_nSec = 60 Then

m_nSec = 0

INC m_nMin

If m_nMin = 60 Then

m_nMin = 0

INC m_nHour

If m_nHour = 24 Then

m_nHour = 0

INC m_nDay

If m_nDay = 30 Then

m_nDay = 1

INC m_nMonth

If m_nMonth = 12 Then

m_nMonth = 1

INC m_nYear

Else

INC m_nMonth

End If

Else

INC m_nDay

End If

Else

INC m_nHour

End If

Else

INC m_nMin

End If

Else

INC m_nSec

End If

X = (5773 * AbSin(137 * m_nSec) * AbCos(173 * m_nMin) * AbSin(137 * m_nHour)) + _

(2377 * AbSin(237 * m_nDay) * AbCos(117 * m_nMonth) * AbCos(m_nYear))

m_fCounter = m_fCounter + 1

If m_fCounter > 1E+99 Then m_fCounter = 0

X = X + Abs(Sin(m_fCounter) + Log(1 + m_fCounter))

NextRand = X - Int(X)

End Function

Calculating the value for variable X is more of an art than a science (at least in my humble opinion). You can develop so many different kinds of expression to calculate X--some better than others. I tried using the modulo operator in a "creative" way, but found that using sin and cos function works rather well.

Namir

*Edited: 15 Feb 2010, 8:52 a.m. after one or more responses were posted*