使用递归测试(条件)添加连续的整数

时间:2015-03-13 05:50:35

标签: scheme sicp

我的递归函数正确地对ab之间的所有整数求和。但是,当我交换我的参数时,结果是不正确的。我正在读SICP。我的代码是(方案):

 (define (sum-integers a b)
   (if (> a b)
      (if (= (- a 1) b)
       (+ a b)
        (+ a(sum-integers (- a 1) b)))
     (+ a (sum-integers (+ a 1) b))))

     (sum-integers 5 2)
     (sum-integers 2 5)

我确定我的编译器是应用顺序,所以我认为输出应该是相同的。

      (sum-integers 5 2)
      (sum-integers 2 5)

事实上,

  (sum-integers 5 2) ==> 14
  (sum-integers 2 5) ==> 25

但是2 + 3 + 4 + 5 = 5 + 4 + 3 + 2 = 14。

为什么我的结果不同?

2 个答案:

答案 0 :(得分:0)

当您发送5,2对2,5:

时,条件if (> a b)会创建不同的流量

当您发送a=5,b=2时,它意味着a > b,因此我们将进入if,并且从5-1 > 2开始递归调用将(+ a(sum-integers (- a 1) b)) }}

当您发送a=2, b=5时,条件if (> a b)将返回false,递归调用将是最后一行:(+ a (sum-integers (+ a 1) b))

如你所见:
(+ a (sum-integers (- a 1) b))与以下内容不同:
(+ a (sum-integers (+ a 1) b))

所以难怪你得到不同的结果。

答案 1 :(得分:0)

在显示错误的第二个测试用例中,您的循环不会在a = 6b = 5之前终止。然后它增加了额外的6和5到总共14,得到25。

你发现这个bug很难找到的原因可能是因为代码比它更复杂,或者因为你还没有学会如何跟踪递归代码。

我还注意到你的代码缩进不一致。让你的编辑为你缩进你的代码,帮助你遵循逻辑。

我已经在评论中提到了@alfasin设计的代码。您可以看到简单性使其更容易调试。如果a > b那么我们只需交换参数并继续进行。

我认为考虑这个问题的关键是确保你想要重复的操作(这里是加法)只在你的函数中出现一次。

(define (sum2-integers a b)
  (if (> a b)
    (sum2-integers b a)   ; if the wrong way round, swap them
    (if (= a b)           ; termination condition
       b
       (+ a (sum2-integers (+ a 1) b)))))

> (sum2-integers 5 2)
14
> (sum2-integers 2 5)
14

进一步走向简单化。我发现多路条件分支cond比嵌套if更易读,因为这段代码中确实有三个分支。

(define (sum3-integers a b)
  (cond [(> a b) (sum3-integers b a)]
        [(= a b) b]
        [else (+ a (sum3-integers (+ a 1) b))]))