通过HtDP并遇到一个问题:设计函数乘法。它使用自然数n并将其与任意数x相乘而不使用*。
这就是我提出的:
(define (multiply n x)
(cond
[(= x 1) n]
[else (+ n (multiply n (- x 1)))]))
它有效,但我认为这不是最好的解决方案。因为这可以作为for循环解决,基于我的理解,这应该是尾递归的。
答案 0 :(得分:4)
现在其他人已经向您展示了如何使函数尾递归,这里是一个函数的替代版本,用于乘以两个正整数,这比你给出的要快得多。你看到这个功能是如何运作的吗?
(define (times x y)
(let loop ((x x) (y y) (z 0))
(if (zero? x) z
(loop (quotient x 2) (+ y y)
(if (odd? x) (+ y z) z)))))
答案 1 :(得分:3)
尾递归解的关键点:保持不变的n * x + r = const。在这种情况下,当x为零时,r包含n * x。
(define (iter-mul n x r)
(cond ((= x 0) r)
(else (iter-mul n (- x 1) (+ r n)))))
您可以将其用作:
(define (mul n x) (iter-mul n x 0))
答案 2 :(得分:2)
可能不是最优雅的,但这至少是尾递归的:
(define (acc a n x)
(if(= x 0)
a
(acc (+ a n) n (- x 1))))
(define (multiply n x)
(acc 0 n x))
答案 3 :(得分:2)
通过使用accumulator参数存储结果,可以很容易地将过程转换为尾递归。以下是为n >= 0
和x >= 0
定义的,我使用的是名为let
(loop
是尾递归过程,不是一个循环结构),以避免显式定义一个辅助过程或向该过程添加另一个参数。这是如何做到的:
(define (multiply n x)
(let loop ((acc 0)
(x x))
(cond
[(= x 0) acc]
[else (loop (+ n acc) (- x 1))])))
另请注意,您的代码中存在错误,请尝试运行(multiply 1 0)
- 无限循环。