对小于 n 的正数求和

Sum numbers that are positive which is less than n

(defun sum (n) 
  (if (n<0) 0 n-1) ;; if n<0, add 0. Else add the next smallest.
  (sum (n-1)))

到目前为止,我得出了这样的结果,但我不确定如何声明一个变量来存储我想要的总和 return。

请注意,您正在为 m = n-1 实现 1+2+...+m,它接受一个简单的公式:

(lambda (n)
  ;; You could inject n-1 on the formula to get n.(n-1)/2
  ;; (like in Vatine's answer), but here I just decrement 
  ;; the input  to show how to modify the local variable 
  ;; and reuse the formula linked above to sum up-to m.
  (decf n) 
  (if (minusp n) 
    0 
    (/ (* n (1+ n)) 2)))

迭代版本也可以,做简单循环时不需要递归:

(lambda (n) (loop :for x :below n :sum x))

关于您的代码:

  • Space很重要1n<0读作名字的符号"N<0"(默认大写)。 n-1 也是如此,它是一个名为 "N-1".

  • 的符号
  • (n<0) 将尝试 运行 名为 n<0 的函数。 (n-1) 也是如此。

  • 比较:可以用(minusp n)(< n 0)
  • 递减:可以使用(1- n)(- n 1)

如果你写的是正确的,像这样:

(defun sum (n) 
  (if (< n 0) 0 (- n 1)) 
  (sum (- n 1)))

...还有问题:

  • 你希望你的 (n-1) 实际上减少 n 但这里 if 只计算一个值而没有产生副作用。

  • 你无条件调用(sum (n-1)),意思是:无限递归。前面的 if 返回的值总是被忽略。


1:详见构成终止字符:2.1.4 Character Syntax Types

编辑:zerop > minusp 以检查负数,已修复以适应 OP 问题

前段时间我使用过 Lisp,但如果我没记错的话,最后的评估会返回。您的问题的递归解决方案如下所示:

 (defun sum (n)  
    (if (<= n 0) 0 ;;if n is less or equal than 0 return 0
        (+ (- n 1) (sum (- n 1))))) ;; else add (n-1) to sum of (n-1)

在 Lisp 中,所有的比较器函数都是函数,所以它需要是 (< n 0)(- n 1)(或者更简洁,(1- n))。

您不需要保留中间值,您可以简单地边加边用。但是,由于您求和为 "less than n" 而不是 "to n",所以这很复杂,因此如果您想递归执行此操作,则需要使用辅助函数。

更好的是,如果你仔细阅读标准(在线很容易获得,如 the Common Lisp HyperSpec,你迟早会看到关于迭代的章节,其中 loop 工具可以做你想做的一切想要。

因此,如果我需要这样做,我会执行以下操作之一:

(defun my-sum (n)
   (/ (* n (1- n)) 2))

(defun my-sum (n)
   (loop for i below n
         sum i))

如果我绝对需要让它递归,我会使用类似的东西:

(defun my-sum (n)
   (labels ((sum-inner (i)
              (if (< i 1)
                0
                (+ i (sum-inner (1- i))))))
     (sum-inner (1- n))))

这(几乎)与定义一个名为 sum-inner 的全局函数相同,后者可能更适合用于调试目的。但是,由于 sum-inner 不太可能有任何其他用途,因此我将其设为本地。