我的递归函数正确地对a
和b
之间的所有整数求和。但是,当我交换我的参数时,结果是不正确的。我正在读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。
为什么我的结果不同?
答案 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 = 6
和b = 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))]))