正数小于n的和数

时间:2016-02-09 09:17:08

标签: lisp common-lisp

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

到目前为止,我发布了类似的内容,但我不知道如何声明一个变量来存储我想要返回的总和。

3 个答案:

答案 0 :(得分:2)

请注意,您正在为 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))

关于您的代码:

  • 空间事项 1 n<0被读作名称的符号&#34; N&lt; 0&#34; (默认为upcased)。同样适用于n-1,这是一个名为&#34; N-1&#34;的符号。

  • (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

答案 1 :(得分:1)

编辑:zerop&gt;减去检查负数,修正以适合OPs问题

前段时间我使用过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)

答案 2 :(得分:1)

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

您不需要保留中间值,您可以随时添加内容。但是,由于你总结为“小于n”而不是“到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不太可能有任何其他用途,我将其设为本地。