More on Random

Bob Arning arning at charm.net
Thu Jun 10 19:43:24 UTC 1999


On Thu, 10 Jun 1999 13:39:24 -0400 "David N. Smith \(IBM\)" <dnsmith at watson.ibm.com> wrote: 
>I suspect that the problem is that Time millisecondClockValue times the
>hash value is answering a value greater than m (16r7FFFFFFF). I'd suggest
>the following code instead. It guarantees that the self seed value is never
>greater than m/2, so the test in #nextValue should never produce a negative
>value after adding m. (If the mask is 16r7FFFFFFF, it is possible to get an
>answer of 1.0 when clock*hash has all ones.)
>
>initialize
>	" Set a reasonable Park-Miller starting seed "
>	seed := Time millisecondClockValue bitAnd: 16r3FFFFFFF.
>
>	a := 16r000041A7 asFloat.    " magic constant =      16807 "
>	m := 16r7FFFFFFF asFloat.    " magic constant = 2147483647 "
>	q := (m quo: a) asFloat.
>	r  := (m \\ a) asFloat.
>
>BTW, does anyone know if there is any definition for the value returned
>from Time millisecondClockValue except that it be a positive integer?

millisecondClockValue
	"Answer the number of milliseconds since the millisecond clock was last 
	reset or rolled over."

	^ self primMillisecondClock

primMillisecondClock
	"Primitive. Answer the number of milliseconds since the millisecond clock
	 was last reset or rolled over. Answer zero if the primitive fails.
	 Optional. See Object documentation whatIsAPrimitive."

	<primitive: 135>
	^ 0

primitiveMillisecondClock
	"Return the value of the millisecond clock as an integer. Note that the millisecond clock wraps around periodically. On some platforms it can wrap daily. The range is limited to SmallInteger maxVal / 2 to allow delays of up to that length without overflowing a SmallInteger."

	self pop: 1.  "pop rcvr"
	self push: (self integerObjectOf: (self ioMSecs bitAnd: 16r1FFFFFFF)).

Since this last (note the comment) is the source for the VM, it seems clear that there is a range of 0..536870911. The precise meaning of ioMSecs is platform dependent. On the Mac it returns milliseconds since the system was rebooted (although what happens after 18446744073709551616 microseconds  (2 raisedTo: 64) is unclear. Given that it's over a half million years, who cares?

>I think Dan added the multiply by self hash; I'm not sure why. Anyone have
>any ideas?

My guess would be so that two Randoms instantiated within the same millisecond would have different seeds (or, at least, probably would). So, a better idea might be:

	" Set a reasonable Park-Miller starting seed "
	seed := Time millisecondClockValue bitXor: self hash.

or, to be incredibly safe (since a seed of zero is also a disaster):

	seed := (Time millisecondClockValue bitXor: self hash) max: 1.

Cheers,
Bob





More information about the Squeak-dev mailing list