Lisp 力量之和
Lisp Sum of power
定义一个函数 "power" 接受两个输入参数 m 和 n,以及 returns m^n。然后,通过使用函数 "power",定义一个函数 sum_power 接受两个输入参数 m 和 n 和 returns 总和:(1^n + 2^n + 3^n + .... + m^n).
int 第一个函数我根据第二个函数中的给定参数计算幂和幂。但是程序报错:程序堆栈溢出。重启...
我找不到我的错误。函数power没问题我查了下
(defun power(m n)
(let ((result 1))
(dotimes (count n result)
(setf result (* m result)))))
(defun sum_power (m n)
(if (= 0 m)
0
(+ (powern m)
(sum_power (1- m) n))))
好的问题是你的函数 sum_power 当你传递变量 m
表达式 (- 1 m)
第一次是无限循环,因为例如
for m = 5 first time (- 1 m) => -4 (new m = -4) second time (- 1 m)
=> 5 (new m = 5)
重新开始,这是一个递归无限循环,您永远不会到达 1,所以这是溢出的情况
改用构建函数 (1- m)
来减小 m 的值,或者如果需要 (- m 1)
所以新函数将是这样的,而且这不是尾递归,所以对于大 m 和 n 会花费很多时间,但根据您的需要它应该可以工作,并且此函数的格式更好,请在编写 lisp 函数时采取 fromatting 以便于阅读
(defun sum_power (m n)
(if (= 1 m)
1
(+ (power n m) (sum_power (1- m) n))
您的 sum_power 函数中存在参数顺序错误。当给定两个参数时,标准 lisp 函数 -
从第一个参数中减去第二个参数,即 (- 1 m)
将从一个中减去 m 而不是从 m 中减去 1,正如您可能预期的那样,因此您的结果将是一个负整数并且您的基本情况 (= 1 m)
将永远不会达到。为了使您的代码正常工作,您必须将参数交换为 -
因此 (- m 1)
或者您可以使用 lisp 函数 1-
(1- m)
从其唯一参数中减去一个因此您的代码的更正版本如下:
(defun sum_power (m n)
(if (= 1 m)
1
(+ (power m n) (sum_power (1- m) n))))
在不相关的旁注中,lisp 允许在函数、变量和宏名称中使用比大多数其他语言更多的字符,因此您可以使用 sum-power 而不是 sum_power,事实上它是可以说是更好的 lisp 风格使用连字符连接多词标识符名称而不是下划线(如在 C 中使用)或驼峰式大小写(如 Java 中使用的 sumPower)。其次,右括号通常不写在单独的一行上,而是与右括号前的最后一个表达式在同一行,正如我在上面的更正版本中所做的那样。这些只是惯例,如果您愿意,您可以遵循它们,但您没有义务。
为什么不用高阶函数和循环宏?我认为这样更具可读性:
(defun power (n m)
(reduce #'* (loop for x below n collect m))
(defun sum-power (n m)
(reduce #'+ (loop for x from 1 to m collect (power x n)))
定义一个函数 "power" 接受两个输入参数 m 和 n,以及 returns m^n。然后,通过使用函数 "power",定义一个函数 sum_power 接受两个输入参数 m 和 n 和 returns 总和:(1^n + 2^n + 3^n + .... + m^n).
int 第一个函数我根据第二个函数中的给定参数计算幂和幂。但是程序报错:程序堆栈溢出。重启... 我找不到我的错误。函数power没问题我查了下
(defun power(m n)
(let ((result 1))
(dotimes (count n result)
(setf result (* m result)))))
(defun sum_power (m n)
(if (= 0 m)
0
(+ (powern m)
(sum_power (1- m) n))))
好的问题是你的函数 sum_power 当你传递变量 m
表达式 (- 1 m)
第一次是无限循环,因为例如
for m = 5 first time (- 1 m) => -4 (new m = -4) second time (- 1 m) => 5 (new m = 5)
重新开始,这是一个递归无限循环,您永远不会到达 1,所以这是溢出的情况
改用构建函数 (1- m)
来减小 m 的值,或者如果需要 (- m 1)
所以新函数将是这样的,而且这不是尾递归,所以对于大 m 和 n 会花费很多时间,但根据您的需要它应该可以工作,并且此函数的格式更好,请在编写 lisp 函数时采取 fromatting 以便于阅读
(defun sum_power (m n)
(if (= 1 m)
1
(+ (power n m) (sum_power (1- m) n))
您的 sum_power 函数中存在参数顺序错误。当给定两个参数时,标准 lisp 函数 -
从第一个参数中减去第二个参数,即 (- 1 m)
将从一个中减去 m 而不是从 m 中减去 1,正如您可能预期的那样,因此您的结果将是一个负整数并且您的基本情况 (= 1 m)
将永远不会达到。为了使您的代码正常工作,您必须将参数交换为 -
因此 (- m 1)
或者您可以使用 lisp 函数 1-
(1- m)
从其唯一参数中减去一个因此您的代码的更正版本如下:
(defun sum_power (m n)
(if (= 1 m)
1
(+ (power m n) (sum_power (1- m) n))))
在不相关的旁注中,lisp 允许在函数、变量和宏名称中使用比大多数其他语言更多的字符,因此您可以使用 sum-power 而不是 sum_power,事实上它是可以说是更好的 lisp 风格使用连字符连接多词标识符名称而不是下划线(如在 C 中使用)或驼峰式大小写(如 Java 中使用的 sumPower)。其次,右括号通常不写在单独的一行上,而是与右括号前的最后一个表达式在同一行,正如我在上面的更正版本中所做的那样。这些只是惯例,如果您愿意,您可以遵循它们,但您没有义务。
为什么不用高阶函数和循环宏?我认为这样更具可读性:
(defun power (n m)
(reduce #'* (loop for x below n collect m))
(defun sum-power (n m)
(reduce #'+ (loop for x from 1 to m collect (power x n)))