The Museum of HP Calculators

HP Forum Archive 19

[ Return to Index | Top of Index ]

Random Number Generation Challenge (sort of)
Message #1 Posted by Namir on 13 Feb 2010, 9:07 a.m.

Hi All,

I am trying to write a random number generator on my HP41CX such that I use the built-in time module to generate either an initial seed for a sequence of random numbers, or generate random numbers outright. Using the values for the current time (and also date) has the potential of generating unique initial seed values.

I think the solution involves the values of time, date, and possibly some sort of a counter.

The simpler the solution the better. So let's put our math thinking caps, shall we!

Namir

PS: I am also trying to solve the same problem with Excel. Of course using VBA code I have a lot of options for more complex/elaborate solutions and more speed.

Edited: 13 Feb 2010, 9:16 a.m.

      
Re: Random Number Generation Challenge (sort of)
Message #2 Posted by Vladan Dugaric on 13 Feb 2010, 9:54 a.m.,
in response to message #1 by Namir

From http://www.hpmuseum.org/software/41/41ranjm.htm

01  LBL "RNG4"
02  DATE
03  TIME
04  +
05   E49
06  *
07  PI
08  MOD
09  LN1+X
10  R-D
11  FRC
12  END

That's what I use.

This one will always make a new random number, it does not have the capability of regenerating a given sequence. It is a good starting point for both functions, though, since the routine can be used as a seed, then plugged into another RNG from the same URL that just uses a given seed.

Vladan

Edited: 13 Feb 2010, 9:57 a.m.

            
Re: Random Number Generation Challenge (sort of)
Message #3 Posted by Namir on 13 Feb 2010, 11:09 a.m.,
in response to message #2 by Vladan Dugaric

Thank you Vladan!!!

Namir

      
Re: Random Number Generation Challenge (sort of)
Message #4 Posted by Namir on 14 Feb 2010, 11:58 a.m.,
in response to message #1 by Namir

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

            
Re: Random Number Generation Challenge (sort of)
Message #5 Posted by JMBaillard on 14 Feb 2010, 5:10 p.m.,
in response to message #4 by Namir

Hi everyone.
Here is an M-Code function that I wrote to get random numbers.

-"RAND" uses the timer to produce pseudo-random numbers r between 0 and 1 ( 0 < r < 1 ). I don't know if r = 0 may happen. -The content of register X is saved in L-register

084 "D" 00E "N" 001 "A" 012 "R" 0F8 READ 3(X) 128 WRIT 4(L) 130 LDI S&X 010 010 The user memory must be deselected by selecting 270 RAM SLCT a non-existent RAM ( at 010h ) 130 LDI S&X then the Timer 0FB 0FB is 3F0 PRPH SLCT selected 3E8 WRIT 15(e) Set the A/B pointer to A 038 READ DATA 1BC RCR 11 Rotates C-register 11 digits right 046 C=0 S&X The user memory 270 RAM SLCT is selected again 05E C=0 MS 130 LDI S&X 041 041 2A0 SETDEC 10E A=C ALL 04E C=0 ALL 35C PT=12 1D0 LD@PT- 7 210 LD@PT- 8 110 LD@PT- 4 050 LD@PT- 1 090 LD@PT- 2 250 LD@PT- 9 190 LD@PT- 6 1D0 LD@PT- 7 210 LD@PT- 8 1D0 LD@PT- 7 044 CLRF 4 C 070 N=C ALL = 171 ?NCXQ A 064 195C mod C 10E A=C ALL 0B0 C=N ALL 261 ?NCXQ C = 060 1898 A/C 0E8 WRIT 3(X) 3E0 RTN

Best Regards, Jean-Marc.

                  
Re: Random Number Generation Challenge (sort of)
Message #6 Posted by Namir on 14 Feb 2010, 5:29 p.m.,
in response to message #5 by JMBaillard

Cool ........ but it looks Greek to me!!!

:-)

Namir

                  
Re: Random Number Generation Challenge (sort of)
Message #7 Posted by Ángel Martin on 15 Feb 2010, 4:30 a.m.,
in response to message #5 by JMBaillard

Beautiful example Jean-Marc, thanks for sharing it.

There is another implementation on the SandMath module, functions SEEDT and RAND written by Håkan Thörngren "a few years ago" - and published on PPCJ back then. I like it because it uses a memory buffer to store the seed(s). Also the time module is used to obtain an initial seed if the input is zero.

Cheers, ÁM.

Edited: 15 Feb 2010, 4:30 a.m.

            
Re: Random Number Generation Challenge (sort of)
Message #8 Posted by Marcus von Cube, Germany on 15 Feb 2010, 2:23 a.m.,
in response to message #4 by Namir

Namir, having read Donald Knuth I have the feeling that you are on the wrong track. From the top of my head, he states that having a complicated function does not make the pseudo random sequence any better. As a result: There are simple workable solutions like the Linear Congruential Method:
(from the pages cited below.)

Useful link: http://random.mat.sbg.ac.at/ (I'll have to check the pages for myself but they look promising.)

                  
Re: Random Number Generation Challenge (sort of)
Message #9 Posted by Namir on 15 Feb 2010, 5:48 a.m.,
in response to message #8 by Marcus von Cube, Germany

Marcus,

Sure the equation you mentioned is very popular and I used it to write typical pseudo-random number generators. My basic approach in this thread is to use the computer's system date and time as an automatic initial seed OR as a way to generate uniform random numbers outright. Since PC's run fast, a system date/time based algorithm risks of generating large arrays of the same random number. This problem prompted me to think of a using a counter to avoid generating the same numbers. Then, I thought of creating a class for a virtual clock that can be initialized by the actual system clock and then run at it's own pace and totally independent of the actual CPU speed. Thus, my virtual clock ticks each time you generate a random number.

The equation I am using uses all of the components of date and time.

Namir

      
Re: Random Number Generation Challenge (sort of)
Message #10 Posted by Bart (UK) on 15 Feb 2010, 8:05 a.m.,
in response to message #1 by Namir

Quote:
PS: I am also trying to solve the same problem with Excel. Of course using VBA code I have a lot of options for more complex/elaborate solutions and more speed.
I found that many random number generating routines performed poorly with regards to having too much repitition when I required 100's of 1000's of numbers. A very good one I found for Excel was Mersenne-Twister. On the site there are links to several implementations and also an Excel add-in.


[ Return to Index | Top of Index ]

Go back to the main exhibit hall