使用lisp添加两个列表

使用lisp添加两个列表,lisp,common-lisp,Lisp,Common Lisp,我喜欢用lisp列出两个列表。 例如: (1 2 3 4 5) + ( 9 9 9 9 9) = (1 1 2 3 4 4) 然而,当我使用时,我得到了(10 11 12 13 14) (add '(1 2 3 4 5) '(9 9 9 9 9)) (defun add (x y) (setf return-value '()) (loop for i from 0 to (- (length x) 1) do (setf return-value (cons

我喜欢用lisp列出两个列表。 例如:

(1 2 3 4 5) + ( 9 9 9 9 9) = (1 1 2 3 4 4)
然而,当我使用时,我得到了
(10 11 12 13 14)

(add '(1 2 3 4 5) '(9 9 9 9 9))   

(defun add (x y)
  (setf return-value '())
  (loop for i from 0 to (- (length x) 1)
        do (setf return-value (cons (+ (nth i l) (nth i y)) return-value)))
  (reverse return-value))
这意味着它不使用一个和对另一个的进位

你能帮忙吗。
谢谢你的代码有一个以上的错误。。。你真的应该像手动操作一样编程。所以你需要从最后一个数字开始,从右到左处理这个数字。除此之外,您还有一个不知从何而来的变量
l
,并且您的
返回值
不是函数的局部值

我修改了一个我不久前写的计划。对于Common Lisp来说,它可能不是惯用语言,但在这一点上应该会有所帮助:

(defun add (l1 l2)
  (flet ((car0 (lst) (if (null lst) 0 (car lst))))
    (labels ((lp (l1 l2 carry res)
                (if (and (null l1) (null l2) (= 0 carry)) 
                  res
                  (let* ((d1 (car0 l1))        
                         (d2 (car0 l2)) 
                         (ad (+ d1 d2 carry))  
                         (dn (mod ad 10)))
                    (lp (cdr l1) (cdr l2) (truncate (- ad dn) 10) (cons dn res))))))
      (lp (reverse l1) (reverse l2) 0 nil))))
然后


希望这有帮助。

这看起来像是一个家庭作业问题,所以我不打算提供一个固定的解决方案

您似乎错过的是Lisp不知道您正在尝试实现“在base 10中使用进位添加”。另外,想一想你是如何手工加法的。当我计算999+001时,我不能一次计算一个数字,因为单位的进位会一直传播到10^4列

我建议你先写一个函数

(defun add-seqs-special (seq1 seq2 base)
   "Add together two sequences of numbers, assumed to be of the same length.
    Each element is assumed to be at most BASE, the base of the number system
    in which we're working. Moreover, we assume that the addition doesn't
    overflow."
   ;; Exercise for reader...
   )
然后编写一个单独的函数,强制向量具有相同的长度,并在每个向量的开头加上一个零(以确保加法不会耗尽位置)

您的
add seqs special
实现需要从右端开始,一次将两个数字相加,然后如果它们的总和大于
base
(或硬代码
base=10
,则累加一个“进位”数字,但这并不会使程序更容易编写)

要获取序列的元素,可以使用
elt
。如果您将列表作为参数传递,这将不会特别有效,因为列表对于随机访问来说很慢。一旦你写了这段代码,你会发现你并没有真正做随机访问。事实上,您需要向后迭代列表。啊哈!因此,现在您可以编写一个新版本,该版本从反转输入开始,然后继续执行
CDR

事实上,这会更好,因为使用该版本很容易处理空间不足的问题。但是,您似乎对Lisp很陌生,因此我建议您首先编写随机访问版本:如果您习惯于C或Python或其他语言,那么它更易于表达


最后,还有一种完全不同的方法。您正在添加数字,而Lisp已经有了任意精度的算法,因此您可以编写两个函数:
数字到数字
数字到数字
,并且只需在两者之间使用
+
!(如果您以前看过Project Euler的问题,您可能至少用一种语言编写过这些函数)

发布问题时,如果使用“{}”符号突出显示代码部分,阅读起来会更容易。或者你可以用“符号”围绕代码。我在回答中已经说过很多关于如何解决这个问题的内容,但是你可能也对
push
宏感兴趣,它为你做
(setf foo(cons x foo))
的事情。
(defun add-seqs-special (seq1 seq2 base)
   "Add together two sequences of numbers, assumed to be of the same length.
    Each element is assumed to be at most BASE, the base of the number system
    in which we're working. Moreover, we assume that the addition doesn't
    overflow."
   ;; Exercise for reader...
   )