Reputation: 15
The below code gives wrong answer. It should give approximately 0.5 which is the average of an array with many random numbers between 0 an 1. I think the problem is because N is "to big", or perhaps the precision on the generated random number?. The code works well for smaller values of N (10^7, 10^6, etc). Some advices will be helpful.
Thank you in advance.
(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)))
Upvotes: 0
Views: 104
Reputation: 139321
Precision of floating point numbers
You are computing with single precision floating point numbers. By adding up all random numbers you get a single-float number. The more numbers you add, the larger the float will be. This eventually causes your result to have not enough precision.
double-floats like 1.0d0
have a higher precision than single-floats like 1.0s0
. By default 1.0
is read as a single-float. (RANDOM 1.0d0)
will compute a double float.
(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))))
Example:
CL-USER 58 > (test (expt 10 8))
0.4999874882753848D0
Style
Please use common Lisp programming style when programming in Common Lisp:
defparameter
, don't name it n
, but *n*
.See my example above.
Upvotes: 4