Re: Is there something wrong with random function?
Pascal Bourguignon <[email protected]> Thu, 16 Nov 2017 14:45:22 +0100
| Newsgroups | gmane.lisp.clisp.general |
|---|---|
| Message-ID | <[email protected]> |
> On 16 Nov 2017, at 14:16, <[email protected]> <[email protected]> wrote: > > Jean Louis wrote: > > (defun random-number (&key (digits 6)) > "Returns the random number with 6 digits by default" > (setf *random-state* (make-random-state)) > (let ((fstr (make-array '(0) :element-type 'base-char :fill-pointer 0 :adjustable t))) > (with-output-to-string (s fstr) > (dotimes (ti digits) > (princ (character (write-to-string (random 10))) s))) > (read-from-string fstr))) > > Don already found the bug, but nobody commented about style. > This function is overly convoluted. Think again about what you want to achieve. > What you're doing above is > Number -> print -> string -> character -> print -> collecting-stream -> adjustable-string -> number > Ouch. Just go straight to your goal. (defun random-number (&key (digits 6)) "Returns the random number with 6 digits by default" (random (expt 10 6))) However, this is wrong! For example: (setf *print-base* 3) (random-number) ;; --> 102222200011 ;; NOT 6 digits!!! Instead, let's add a base parameter (and take *print-base* by default): (defun random-number (&key (digits 6) (base *print-base*)) "Returns the random number with 6 digits by default" (random (expt base 6))) (random-number) ;; --> 112101 (loop repeat 10 collect (random-number)) ;; --> (879023 606819 686060 963306 143047 550980 621150 144785 90563 830616) (defun replength (n &key (base *print-base*)) (ceiling (log n base))) (defun subrep (num start end &key (base *print-base*)) "Digits are indexed from least significant." (check-type num integer) (check-type start (integer 0)) (check-type end (integer 0)) (check-type base (integer 2)) (if (< start end) (rem (truncate num (expt base start)) (expt base (- end start))) 0)) (loop for start below 10 collect (subrep 123456789 start (+ start 3))) ;; --> (789 678 567 456 345 234 123 12 1 0) (loop for start below 10 collect (subrep -123456789 start (+ start 3))) ;; --> (-789 -678 -567 -456 -345 -234 -123 -12 -1 0) (defun sign (n) (check-type n real) (cond ((minusp n) -1) ((plusp n) +1) (t 0))) (defun concatrep (a b &key (base *print-base*) length2) (check-type a integer) (check-type b integer) (check-type base (integer 2)) (check-type length2 (or null (integer 0))) (let* ((length2 (or length2 (replength b))) (factor (expt base length2))) (* (sign a) (+ (* (abs a) factor) (mod (abs b) factor))))) (concatrep -123 456) ;; --> -123456 (concatrep -123 12 :length2 3) ;; --> -123012 (concatrep 123 -3 :length2 3) ;; --> 123003 (let ((*print-base* 5)) (prin1-to-string (subrep (concatrep #5r1234 #5r4321) 2 6))) ;; --> "3443" -- __Pascal J. Bourguignon__ Try the IBM Flex font: IBM has freed itself from the tyranny of Helvetica https://qz.com/1124664/ibm-plex-with-its-first-ever-custom-corporate-font-ibm-is-freeing-itself-from-the-tyranny-of-helvetica/ ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot _______________________________________________ clisp-list mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/clisp-list