(Racket/Scheme)减法产生的结果差得令人难以置信



我目前正忙于"如何设计程序"-使用Scheme/Racket;我在R5RS版本的Scheme中发现了一个非常独特的功能。

当进行简单的减法运算时,尽管使用的值精确到小数点,但答案与预期相差甚远。

例如;给定以下减法运算:

(- 5.00 4.90)
=> 0.09999999999999965

人们什么时候应该期待一个干净的0.10?整数减法的效果如预期;

> (- 5 4)
=> 1
> (- 5 4.9)
=> 0.09999999999999965

例如,练习3.1.1

下一步是为每个函数制作示例。确定有多少观众能负担得起3.00美元、4.00美元和5.00美元的票价。使用示例制定一个通用规则,说明如何根据票价计算与会者人数。如果需要,可以编更多的例子。

示例中的规则是,票价每降低0.10美元,就会有15人参加。所以像这样的快速函数会起作用。。

(define (attendees ticket-price)
(+ 120 (* (/ (- 5.00 ticket-price) 0.10) 15)))

然而,这会返回(相当烦人)。。

> (attendance 4.90)
=> 134.99999999999994

因此,在尝试了课本中的(几乎相同的)解决方案之后。。

(define (attendance price)
(+ (* (/ 15 .10) (- 5.00 price))
120))

我也犯了同样的错误。这是我的本地系统特有的吗?我很好奇——事实上,我可以简单地使用某种形式的舍入来纠正这一点;但我宁愿知道为什么它会先发生!

除此之外,我建议任何对Lisp感兴趣的人看看HTDP。略读一下,这似乎是一篇非常温和的文章,非常实用。我确实喜欢SICP,但这更像是一件长期的事情;我似乎花了好几天时间阅读,然后做练习,然后上网上课。HTDP似乎有点像"哦,我有15分钟的空闲时间——我会看看HTDP"。

浮点数并不总是按照您期望的精确值存储。请参阅例如"浮点的危险"。

如果你想要精确的计算,你可以在你的情况下使用整数运算,将值存储在美分而不是美元中。

(define (attendees ticket-price-cents)
(+ 12000 (* (/ (- 500 ticket-price-cents) 10) 1500)))

除了前面的(正确的)答案之外:你真正应该问的问题是:"为什么在其他语言级别中没有发生这种情况?"答案是:许多其他语言级别将5.03解释为一个精确的数字(百分之五和三百),而不是浮点数。

JFYI!

最新更新