Francisco
Francisco

Reputation: 15

code with incorrect result for big N. Common Lisp

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

Answers (1)

Rainer Joswig
Rainer Joswig

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:

  • don't use global variables, if not necessary. Write functions with local variables instead.
  • if you define a global variable with defparameter, don't name it n, but *n*.
  • format and indent your code correctly. Indentation should be done with editor help.
  • don't use parentheses on their own line.

See my example above.

Upvotes: 4

Related Questions