Lisp,嵌套列表中数字的子总数

时间:2013-10-28 18:13:07

标签: lisp common-lisp

我有一个问题,我不能解决,

用户输入列表即

 (total-cost 
   '((anItem 2 0.01) 
     (item 3 0.10) 
     (anotherItem 4 4.10) 
     (item 5 2.51))) 

我需要在最后添加数字,然后返回结果

我的当前代码在每次添加后返回代码。并且还会抛出有关意外类型的错误

(defun total-cost (list)
  (loop with sum = 0
        for x in list
      collect (setf sum (+ sum (last x)))
   )
)

错误:(0.01)' is not of the expected type NUMBER'

感谢任何帮助 谢谢戴尔

5 个答案:

答案 0 :(得分:10)

使用LOOP

CL-USER 19 > (loop for (nil nil number) in '((anItem      2 0.01) 
                                             (item        3 0.10) 
                                             (anotherItem 4 4.10) 
                                             (item        5 2.51))
                   sum number)
6.72

REDUCE是另一种选择:

CL-USER 20 > (reduce '+
                     '((anItem      2 0.01) 
                       (item        3 0.10) 
                       (anotherItem 4 4.10) 
                       (item        5 2.51))
                     :key 'third)
6.72

答案 1 :(得分:5)

Loop有一个关键字sum用于求和,因此您不必使用显式变量也不必使用setf

(defun total-cost (list)
  (loop for x in list sum (third x)))

正如克里斯所说,如果你要找的号码总是最后一个,请使用(car (last x))。或者你可以在我的例子中使用(third x),如果它总是第三个。

另请注意,如果您的目标是仅返还金额,则使用collect是错误的;你的例子(更正)返回

(0.01 0.11 4.21 6.7200003)

而我的回归

6.7200003

请注意,如果你想尽可能地避免舍入错误,你需要使用exponent marker来使它们成为双浮点数,例如:

(total-cost '((anItem 2 0.01D0)
             (item 3 0.10D0) 
             (anotherItem 4 4.10D0) 
             (item 5 2.51D0)))
=> 6.72D0

答案 2 :(得分:3)

last返回列表中的最后一个cons单元格,而不是其值。您需要改为使用(car (last x))

答案 3 :(得分:2)

以防您希望代码为您提供精确的结果而不是简短的结果:

(defun kahan-sum (floats)
  (loop
     :with sum := 0.0 :and error := 0.0
     :for float :in floats
     :for epsilon := (- float error)
     :for corrected-sum := (+ sum epsilon) :do
     (setf error (- corrected-sum sum epsilon) sum corrected-sum)
     :finally (return sum)))

(defun naive-sum (floats) (loop :for float :in floats :sum float))

(let ((floats (loop :repeat 1000 :collect (- (random 1000000.0) 1000000.0))))
  (format t "~&naive sum: ~f, kahan sum: ~f" (naive-sum floats) (kahan-sum floats)))
;; naive sum: -498127420.0, kahan sum: -498127600.0

在此处详细了解其工作原理:http://en.wikipedia.org/wiki/Kahan_summation_algorithm

答案 4 :(得分:0)

晚会很晚......怎么样而不是loop? ; - )

(defun sum-3rd (xs)
  (let ((sum 0))
    (dolist (x xs sum) 
      (incf sum (nth 2 x)))))