对小于 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很重要1:n<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
不太可能有任何其他用途,因此我将其设为本地。
(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很重要1:
n<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
不太可能有任何其他用途,因此我将其设为本地。