Scheme递归乘法实现问题(负数处理异常)
解决Scheme递归乘法的负数无限循环问题
看起来你已经把正数乘法的递归逻辑搞对了,但负数处理的分支确实踩了个常见的递归陷阱——没有让递归向终止条件靠拢。我们先拆解一下问题出在哪,再给你几个修复方案。
问题分析
先把你没写完的代码补全(根据上下文推测):
(define Multiply (lambda (x y) (if (eq? x 0) 0 (if (eq? y 0) 0 ; 若x或y为0,则返回0 (if (> 0 x) (- 0 (+ x (Multiply x (- y 1)))) (if (> 0 y) (- 0 (+ x (Multiply x (- y 1)))) (+ x (Multiply x (- y 1))))))))
当处理负数时,比如计算(Multiply 2 -3),代码会进入y<0的分支,执行(- 0 (+ 2 (Multiply 2 (- -3 1))))——也就是(- 0 (+ 2 (Multiply 2 -4)))。这里的核心问题是:你给y做了(- y 1),当y本身是负数时,这会让它变得更负(-3→-4→-5…),永远达不到终止条件y=0,自然就陷入无限循环了。
另外,用eq?判断数字是否为0也不够规范,Scheme里有专门的zero?函数来做这件事,推荐替换使用。
修复方案
方案1:先统一处理符号,再递归正数乘法
这个思路更清晰:先计算两个数绝对值的乘积,再根据原数的符号决定结果的正负(同号为正,异号为负)。
(define Multiply (lambda (x y) ; 定义辅助函数,只处理正数乘法 (define positive-multiply (lambda (a b) (if (zero? b) 0 (+ a (positive-multiply a (- b 1)))))) (cond ((or (zero? x) (zero? y)) 0) ; 任何数乘0都是0 ; 异或判断:x和y一正一负,结果取反 ((xor (negative? x) (negative? y)) (- 0 (positive-multiply (abs x) (abs y)))) ; 同号则直接返回正数乘积 (else (positive-multiply (abs x) (abs y))))))
方案2:直接在递归中调整负数的步长
如果不想拆分辅助函数,可以直接在递归逻辑里针对y的正负调整步长:当y为负时,每次让y加1(向0靠拢),同时用减法代替加法,保证逻辑正确。
(define Multiply (lambda (x y) (cond ((or (zero? x) (zero? y)) 0) ((positive? y) (+ x (Multiply x (- y 1)))) ; y为正,正常累加 ((negative? y) (- (Multiply x (+ y 1)) x)) ; y为负,每次y+1,等价于累加-x (else 0))))
举个例子,计算(Multiply 2 -3)的递归过程:
- 第一次调用:
y=-3<0,执行(- (Multiply 2 -2) 2) - 第二次调用:
y=-2<0,执行(- (Multiply 2 -1) 2) - 第三次调用:
y=-1<0,执行(- (Multiply 2 0) 2) - 第四次调用:
y=0,返回0,所以第三次结果为(- 0 2)=-2,第二次为(- (-2) 2)=-4,第一次为(- (-4) 2)=-6,完全符合预期。
测试验证
你可以试试这几个用例:
(Multiply 3 4)→ 12(正数正常)(Multiply -3 4)→ -12(x为负)(Multiply 3 -4)→ -12(y为负)(Multiply -3 -4)→ 12(两数同负)(Multiply 0 5)→ 0(边界条件)
这样就能正确处理所有正负情况,不会陷入无限循环啦!
内容的提问来源于stack exchange,提问作者Rene Ferguson
相关产品推荐
相关产品推荐

