大 N. Common Lisp 结果不正确的代码
code with incorrect result for big N. Common Lisp
下面的代码给出了错误的答案。它应该给出大约 0.5,这是一个包含 0 和 1 之间的许多随机数的数组的平均值。我认为问题是因为 N 是 "to big",或者可能是生成的随机数的精度?。该代码适用于较小的 N 值(10^7、10^6 等)。一些建议会有所帮助。
提前致谢。
(defun randvec(n)
(let ((arr (make-array n)))
(dotimes (i n)
(setf (aref arr i) (random 1.0))
)
arr
)
)
(defparameter N (expt 10 8))
(setf *random-state* (make-random-state t))
(defparameter vector1 (randvec N))
(format t "~a~%" (/ (reduce #'+ vector1) (length vector1)))
浮点数的精度
您正在使用单精度浮点数进行计算。通过将所有随机数相加,您将得到一个单浮点数。添加的数字越多,浮点数就越大。这最终会导致你的结果没有足够的精度。
像 1.0d0
这样的双浮点数比像 1.0s0
这样的单浮点数具有更高的精度。默认情况下 1.0
被读取为单浮点数。 (RANDOM 1.0d0)
将计算双浮点数。
(defun randvec (n)
(let ((v (make-array n)))
(dotimes (i n v)
(setf (aref v i) (random 1.0d0))))) ; create a double float random number
(defun test (&optional (n 10))
(setf *random-state* (make-random-state t))
(let ((v (randvec n)))
(/ (reduce #'+ v) (length v))))
示例:
CL-USER 58 > (test (expt 10 8))
0.4999874882753848D0
风格
使用 Common Lisp 编程时请使用 common Lisp 编程风格:
- 如果没有必要,不要使用全局变量。改为使用局部变量编写函数。
- 如果用
defparameter
定义全局变量,不要命名为n
,而是*n*
.
- 正确格式化和缩进代码。缩进应该在编辑器的帮助下完成。
- 不要在自己的行上使用括号。
参见上面的示例。
下面的代码给出了错误的答案。它应该给出大约 0.5,这是一个包含 0 和 1 之间的许多随机数的数组的平均值。我认为问题是因为 N 是 "to big",或者可能是生成的随机数的精度?。该代码适用于较小的 N 值(10^7、10^6 等)。一些建议会有所帮助。
提前致谢。
(defun randvec(n)
(let ((arr (make-array n)))
(dotimes (i n)
(setf (aref arr i) (random 1.0))
)
arr
)
)
(defparameter N (expt 10 8))
(setf *random-state* (make-random-state t))
(defparameter vector1 (randvec N))
(format t "~a~%" (/ (reduce #'+ vector1) (length vector1)))
浮点数的精度
您正在使用单精度浮点数进行计算。通过将所有随机数相加,您将得到一个单浮点数。添加的数字越多,浮点数就越大。这最终会导致你的结果没有足够的精度。
像 1.0d0
这样的双浮点数比像 1.0s0
这样的单浮点数具有更高的精度。默认情况下 1.0
被读取为单浮点数。 (RANDOM 1.0d0)
将计算双浮点数。
(defun randvec (n)
(let ((v (make-array n)))
(dotimes (i n v)
(setf (aref v i) (random 1.0d0))))) ; create a double float random number
(defun test (&optional (n 10))
(setf *random-state* (make-random-state t))
(let ((v (randvec n)))
(/ (reduce #'+ v) (length v))))
示例:
CL-USER 58 > (test (expt 10 8))
0.4999874882753848D0
风格
使用 Common Lisp 编程时请使用 common Lisp 编程风格:
- 如果没有必要,不要使用全局变量。改为使用局部变量编写函数。
- 如果用
defparameter
定义全局变量,不要命名为n
,而是*n*
. - 正确格式化和缩进代码。缩进应该在编辑器的帮助下完成。
- 不要在自己的行上使用括号。
参见上面的示例。