LISP的随机函数的实现

对Autolisp来说,没有生成随机数的函数,一般来说,有如下方法可以产生它:

方法一:用同余函数实现,这是纯LISP的方法。

;;;rand function-some code from Lee Mac,--thanks.
(defun LM:random (Var / x)
  (/ (setq x	4294967296.0
	   seed	(rem (1+ (* 1664525.0
			    (cond (seed)
				  ((getvar var))
			    )
			 )
		     )
		     x
		)
     )
     x
  )
)
(defun Rand (a b var)
  (fix (+ a (* (LM:random var) (- b a -1))))
)

方法二:用系统的相关的变量如cputicks,TDUSRTIMER等实现:

此方法可能会产生一些不是很随机的数。

(defun c:random	()
  (setq seed (getvar "TDUSRTIMER"))
  (setq seed (- seed (fix seed)))
  (rem (* seed 86400) 1)
)

方法三:利用windows系统com中产生随机数。

当前实现Random类基于 Donald E.Knuth 删减随机数生成器算法的修改版本。 有关详细信息,请参阅 D.e。 Knuth。 计算机编程,卷 2 的技术:Seminumerical 算法。 Addison-wesley,Reading,MA,第三个版本,1997年。

(setq rndObj (vlax-create-object "System.Random"))
  (setq x (vlax-invoke rndobj 'nextdouble))
  (setq y (vlax-invoke rndobj 'next))
 
  (defun sysRnd (x y)
    (+ x (* (vlax-invoke rndobj 'nextdouble) (- y x)))
  )

方法四:用vbscript 或者Jscirpt等内部的随机函数产生,然后在lisp用调用脚本语言。

(if
    (or
      (setq wcs (vlax-create-object   "Aec32BitAppServer.AecScriptControl.1"))
      (setq wcs (vlax-create-object "ScriptControl"))
    )
    (vlax-put-property wcs "language" "VBScript")
  )
  (setq str "Randomize
             Function Rand(x,y)\n
                 Rand=x+Rnd*(y-x)\n
             End Function"
  )        
  (vlax-invoke wcs 'addcode str)
 
  (defun wcsRnd(a b)
    (vlax-invoke wcs 'run "rand" a b)
  )

上面的代码经过测试验证,用同余的速度最快,vbs最慢,system.random中间,但同余法的效率并未超过system.random很多,仅仅是几倍的差距。而system.random虽也是伪随机的,但是正确性比同余法高。