;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; This file is part of ICCLE2.
;
; ICCLE2 is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
;
; ICCLE2 is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with ICCLE2. If not, see
The ``bald1`` says "when debugging code containing random ;selections, it is useful to ;recreate a ;prior run that lead to an error". Hence, most languages offer a pseudo-random ;number generator which generates a sequence pf random numbers from some ;seed. Exactly the same sequence of “random” numbers can be recreated by ;resetting the seed and re-running the random sequence. ;
Sadly, I can’t make LISP’s built in random number generator work that ;way. Yes, I’ve tried reseting *random-state* and that did not work. Also, I began to worry ;that what ever I did would not be portable to other LISPs. ;
So the following implements a ;simple pseudo-random number generator. ;
(defparameter *seed0* (random 12000)) (defparameter *seed* *seed0*) (defun reset-seed () (setf *seed* *seed0*)) ;;
This is the Park-Miller multiplicative congruential randomizer ; (CACM, October 88, Page 1195). Creates pseudo random floating ; point numbers in the range 0.0 < x ≤ 1.0.
(defun park-miller-randomizer ()
(let ((multiplier
16807.0d0);16807 is (expt 7 5)
(modulus
2147483647.0d0)) ;2147483647 is (- (expt 2 31) 1)
(let ((temp (* multiplier *seed*)))
(setf *seed* (mod temp modulus))
(/ *seed* modulus))))
;
;
(defun my-random (n)
(let ((random-number (park-miller-randomizer)))
(* n (- 1.0d0 random-number))))
;
(defun my-randone ()
(let ((random-number (park-miller-randomizer)))
(- 1.0d0 random-number)))
;
(defun my-random-int (n)
(let ((random-number (/ (my-random 1000.0) 1000)))
(floor (* n random-number))))
;
(deftest test-random ()
(check
(equalp (random-demo) (random-demo))))
(defun random-demo ()
(let (counts out)
(labels
((sorter (x y) (< (car x) (car y)))
(zap () (setf out nil)
(reset-seed)
(setf counts (make-hash-table)))
(inc (n) (setf (gethash n counts)
(1+ (gethash n counts 0))))
(cache (k v) (push (list k v) out)))
(zap)
(dotimes (i 10000)
(inc (my-random-int 5)))
(maphash #'cache counts)
(sort out #'sorter))))
;