我有一个问题,我不能解决,
用户输入列表即
(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'
感谢任何帮助 谢谢戴尔
答案 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)))))