【问题标题】:Can this be turned into a tail recursive function?这可以变成尾递归函数吗?
【发布时间】:2012-12-30 00:16:36
【问题描述】:

通过HtDP,遇到了一个问题:设计函数乘法。它消耗一个自然数 n 并将其与某个任意数 x 相乘,而不使用 *。

这是我想出的:

(define (multiply n x)
  (cond
    [(= x 1) n]
    [else (+ n (multiply n (- x 1)))]))

它有效,但我认为这不是最好的解决方案。由于这可以作为 for 循环解决,根据我的理解,这应该是尾递归的。

【问题讨论】:

    标签: scheme racket tail-recursion htdp


    【解决方案1】:

    尾递归解法的关键点:保持一个不变的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】:

      现在其他人已经向您展示了如何使函数尾递归,这里是一个函数的替代版本,用于将两个正整数相乘,它比您给出的要快得多。你知道这个函数是如何工作的吗?

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

      【讨论】:

        【解决方案3】:

        可能不是最优雅的,但这至少是尾递归:

        (define (acc a n x)
          (if(= x 0)
            a
            (acc (+ a n) n (- x 1))))
        
        (define (multiply n x)
          (acc 0 n x))
        

        【讨论】:

          【解决方案4】:

          通过使用累加器参数来存储结果,可以轻松地将过程转换为尾递归。以下是为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) - 无限循环。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-10-20
            • 1970-01-01
            • 2023-03-25
            • 2011-09-13
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多