【问题标题】:SICP exercise 1.17 issueSICP 练习 1.17 问题
【发布时间】:2020-08-31 15:37:30
【问题描述】:

我正在 SICP 中做练习 1.18,我遇到了一些麻烦。目标是根据之前的 2 个练习制定一个程序。这个程序实现了所谓的俄罗斯农民方法(或古埃及乘法)。我写了一个代码,但是一个程序就是不想执行。这是我的代码:

#lang sicp
(define (double a) (+ a a)) 
(define (halve a) (/ a 2)) 

(define (r_m a b)
  (iter a b 0))
  
(define (iter a b n)
    (cond ((= b 0) 0)
          ((even? a) (iter (halve a) (double b) (+ n b)))
          (else (iter (halve a) (double b) n))))

因此,当我使用此类参数 (r_m 13 19) 调用我的过程 (r_m) 时,它会在第一次迭代后停止。 (iter (halve a) (double b) (+ n b)(带有参数 13 和 19)给出了这个结果:iter (13/2) 38 19

之后,程序会尝试检查 13/2 是否为奇数。但它无法检查这样的数字 (13/2),因为 odd? 需要一个整数,而不是这个未完成的除法。

由于某种原因,halve 过程在调用时不起作用。我真的不明白为什么,因为其他程序(double 和简单的+ n b)工作正常。

提前谢谢你,希望我的语法不会对你造成太大伤害。

【问题讨论】:

    标签: scheme racket sicp


    【解决方案1】:

    您的程序有几个问题。除此之外,即使halve 以您希望的方式工作,b 怎么会变成零?这不是唯一的问题!

    然而,halve 的特殊情况发生是因为您假设编程语言做它们通常做的事情:对机器方便的错误算术,而不是对人类方便的正确算术。 Scheme 努力做到正确 算术。数学上,13/2 是多少?它不是 6、7 或 3,而是 13/2 或 6 + 1/2:它是有理数,而不是整数。

    如果你想要下一个小于 13/2 的整数,你想要得到它的方法是在除法之前减去 1:(halve (- 13 1)) 正好是 6。因此,如果您将 cond 子句更改为 (halve (- a 1)),您的程序将更接近工作(但实际上它将无法终止,因此从某种意义上说,它将远离工作......)。

    【讨论】:

    • 感谢您的帮助。我更改了halve 部分,添加了cond 以检查数字是否为奇数(如果是,则执行(- 1))。然后将这个(cond ((= b 0) 0) 更改为这个(cond ((= a 0) n)。该程序现在按预期工作。对于数字 13 和 19,它会返回正确答案:247。谢谢!