cg-Cad

Lisp »Tips 'n Tricks »Numeri casuali in AutoLISP »1 | 2 | 3

Un numero casuale è un numero estratto da un insieme di valori equiprobabili.
Un programma può generare solo numeri pseudo-casuali. Scritto il programma, tutti i numeri da esso prodotti possono essere dedotti, leggendo il codice (o conoscendo l'algoritmo) quindi non sono veramente casuali.
In diversi punti di "Tips and Tricks" ho usato la funzione (rn); questa funzione preleva il valore dalla variabile DATE e lo impasta ad altri numeri con una serie di operazioni:

; Random number generator, from 0.000 to 0.999
(defun rn () 
   (if (not sd) (setq sd (getvar "DATE")))
   (setq md 65536 mx 25173 nc 13849 sd 
     (rem (+ (* mx sd) nc) md)
   )
   (setq nx (/ sd md))
)

(rn) applica, in modo parziale, il metodo x<-(a * x[i-1] + c) mod m (1) dove mod è l'operatore modulo che fornisce il resto della divisione (rem in Lisp), a c m sono numeri interi costanti e x è il "seme" (seed) della sequenza. Nell'esempio la x (sd) prende il valore della variabile DATE.
L'uso di DATE nella funzione (rn) è un artificio per dare un valore arbitrario a x, tuttavia il risultato non viene rimesso in gioco quindi il risultato della funzione (rn) è un numero arbitrario.

Il metodo completo è preso un numero intero arbitrario x lo si moltiplica per a (a * x), gli si aggiunge c (a * x + c) e si salva in x <- il resto della divisione per m (a * x + c) mod m, ripetendo n volte il procedimento x<-(a * x[i-1] + c) mod m.
Il risultato è un insieme di interi compresi tra 0 e m-1.

Ecco un lisp che genera 100 numeri interi casuali compresi tra 0 e 99:

;;;    rand.lsp - 15 Febbraio 2004
;;;    (C) by Claudio Piccini
;;;    http://www.cg-cad.com/
;;;
;;;    Motore di numeri casuali
;;;

(defun rn (sd)
 (setq m 100 b 25173 c 13849 sd 
  (rem (+ (* b sd) c) m)
 )
)

(defun c:rand ()
 (setq sd 1)
 (setq ls nil)
 (repeat 100
  (setq sx (rn sd))
  ; salva i numeri nella lista ls
  (setq ls (append ls (list sx)))
  (setq sd sx)
 )
)
;;;eof

Command: !ls
(22 55 64 21 82 35 4 41 42 15 44 61 2 95 84 81 62 75 24 1 ->22 55 64 21 82 35 4 41 42 15 44 61 2 95 84 81 62 75 24 1 22 55 64 21 82 35 4 41 42 15 44 61 2 95 84 81 62 75 24 1 22 55 64 21 82 35 4 41 42 15 44 61 2 95 84 81 62 75 24 1 22 55 64 21 82 35 4 41 42 15 44 61 2 95 84 81 62 75 24 1)

Con m=381 b=19 c=13849 e sd=0 il risultato è:

Command: !ls
(133 374 0 133 374 0 133 374 0 133 374 0 133 374 0 133 374 0 133 374 0 133 374 0 133 374 0 133 374 0 133 374 0 133 374 0 133 374 0 133 374 0 133 374 0 133 374 0 133 374 0 133 374 0 133 374 0 133 374 0 133 374 0 133 374 0 133 374 0 133 374 0 133 374 0 133 374 0 133 374 0 133 374 0 133 374 0 133 374 0 133 374 0 133 374 0 133 374 0 133)

Con m=65521 b=15937 c=33503 e sd=0 (2) il risultato è:

Command: !ls
(33503 40185 59594 56186 59799 47221 20374 11865 32402 53176 50801 6043 24924 58989 45888 5157 57278 34417 60941 32437 21282 2520 30370 36566 42071 42637 21081 9712 53045 59726 63198 31217 37879 632 15453 14525 32735 52996 65065 39062 49576 8476 11213 59317 31544 7598 40021 1245 22205 35667 63807 39742 10250 43900 34565 60861 2376 28677 49877 22480 28435 58862 53040 45562 51375 46462 45576 12409 53358 2890 30170 59695 27798 62748 1356 22145 62262 52973 26119 37093 54182 30778 52283 37117 43544 61320 44628 39484 26327 10418 34955 51796 7276 18945 39200 21168 20290 49098 56547 47208)

Questo lisp migliora il motore di numeri casuali:

;;;    rrand.lsp (ver. 1.0) - 15 Febbraio 2004
;;;    (C)2004 by Claudio Piccini
;;;    http://www.cg-cad.com/
;;;
;;;    Motore di numeri casuali
;;;

(defun rn (sd)
 (setq m 65521 b 15937 c 33503 sd 
  (rem (+ (* b sd) c) m)
 )
 (setq sd (* (/ sd m) 20))
)

(defun c:rrand ()
 (setq sd 0.0)
 (setq ls nil)
 (repeat 100
  (setq sx (rn sd))
  ; salva i numeri nella lista ls
  (setq ls (append ls (list (fix sx))))
  (setq sd sx)
 )
)

Command: !ls
(10 19 7 6 0 13 14 2 1 16 11 4 10 1 17 17 14 2 0 14 19 4 12 12 12 9 15 5 17 15 7 4 13 16 10 2 1 17 14 0 14 1 19 3 5 16 12 9 18 18 0 10 3 5 15 5 15 6 1 18 0 10 2 1 16 10 0 14 1 19 4 14 0 11 7 4 12 12 11 7 8 11 8 9 17 16 11 6 2 3 8 11 8 9 15 6 3 5 18 1)

Il numero 20 genera 100 numeri casuali compresi tra 0 e 19.

Infine questa versione del lisp chiede quanti numeri salvare nel file NC.TXT (nella cartella aperta) e il relativo intervallo, da 0 a r-1.

;;;    rrand.lsp (ver. 1.1) - 15 Febbraio 2004
;;;    (C)2004 by Claudio Piccini
;;;    http://www.cg-cad.com/
;;;
;;;    Motore di numeri casuali
;;;

(defun rn (sd)
 (setq m 65521 b 15937 c 33503 sd 
  (rem (+ (* b sd) c) m)
 )
 (setq sd (* (/ sd m) r))
)

(defun c:rrand ( / f1 nomeDir nf)
 (setq sd 0.0)
 (setq nomeDir (getvar "dwgprefix"))
 (setq nf (strcat nomeDir "nc.txt"))
 (setq f1 (open nf "w"))
 (initget (+ 1 2 4))
 (setq conta (getint "\nQuanti numeri? "))
 (initget (+ 1 2 4))
 (setq r (getint "\nIntervallo da 0 a? "))
 (repeat conta
  (setq sx (rn sd))
  ; salva la stringa sx (itoa sx) 
  ; nel file NC.TXT
  (write-line (itoa (fix sx)) f1)
  (setq sd sx)
 )
 (close f1)
)
;;;eof

Con conta=20 e r=10 il risultato è:

5
7
3
3
3
4
5
9
7
3
2
1
9
8
6
2
0
5
9
7

(1) Algoritmi in C++, R. Sedgewick Ed. Addison-Wesley
(2) C Laboratorio di programmazione

Lisp »Tips 'n Tricks

Ultimo Aggiornamento_Last Update: 15 Febbraio 2004