[alicebot-archcomm] more random <random>
John Foderaro
alicebot-archcomm@list.alicebot.org
Sun, 28 Apr 2002 09:30:47 -0700
>> The problem is that if two different <random> elements are
>> imagined to each have an independent random "space", tying all of their
>> choices to the same sequence of pseudo-random numbers really throws a
>> wrench into the works.
I know what you're saying but I don't think there is anything to worry
about. Random number generators will produce a nice even distribution
but only over a very large number of samples. If you're asking
for a random number between 0 and 4 (inclusive) and call random 5
times you almost certainly won't get each number chosen once.
And that's the correct result since the odds of that happening
if the random number generator were truly random is very small.
I wrote little test program to show this:
If I chose 5 random numbers I get one 2, two 3's and 2 4's.
cl-user(31): (testit :count 5)
0: 0 0.0d0
1: 0 0.0d0
2: 1 0.2d0
3: 2 0.4d0
4: 2 0.4d0
If I chose one million random numbers I get this distribution.
Now the distribution is very nice over the 5 possible numbers:
cl-user(32): (testit :count 1000000)
0: 199398 0.199398d0
1: 199834 0.199834d0
2: 200394 0.200394d0
3: 200158 0.200158d0
4: 200216 0.200216d0
Suppose that after every 7th random number I obtain I call
the random number generator and throw away the value. This is
simulating the case of running another <random> tag with a
different number of elements.
We still end up with a nice distribution:
cl-user(34): (testit :count 1000000 :toss-out 7)
0: 200119 0.200119d0
1: 200194 0.200194d0
2: 199914 0.199914d0
3: 199833 0.199833d0
4: 199940 0.19994d0
So I don't think there is any need to create multiple independent
random number sequences, one for each <random> tag.
--john foderaro
ps. here's my test code
(in-package :user)
(defvar results (make-array 5))
(defun testit (&key (count 10000) (toss-out 0))
(dotimes (i (length results)) (setf (svref results i) 0))
(dotimes (i count)
; throw out a random result periodically
(if* (and (> toss-out 0)
(zerop (mod i toss-out)))
then (random (+ (length results) 4)))
; now collect some random info
(incf (svref results (random (length results)))))
(dotimes (i (length results))
(format t "~d: ~d ~s~%"
i
(svref results i)
(/ (float (svref results i) 1.0d0) count)))
)