(球拍/方案)减法产生的结果是令人难以置信的小幅度

Fer*_*don 2 lisp math floating-point precision scheme

我正在搞乱" 如何设计程序 " - 使用Scheme/Racket; 我在R5RS版本的Scheme中遇到了一个非常特殊的功能.

在进行简单减法时,尽管使用带有小数点精度的值,但答案与预期的完全不同.

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

(- 5.00 4.90)
=> 0.09999999999999965
Run Code Online (Sandbox Code Playgroud)

当一个人肯定期待一个干净的0.10?整数减法按预期工作;

> (- 5 4)
 => 1
> (- 5 4.9)
 => 0.09999999999999965
Run Code Online (Sandbox Code Playgroud)

举例来说,练习3.1.1:

下一步是为每个功能组成示例.确定有多少与会者可以以3.00美元,4.00美元和5.00美元的门票价格购买节目.使用示例来制定一般规则,显示如何根据故障单价格计算与会者人数.如果需要,请填写更多示例.

示例中的规则是,每售出0.10美元的票价,就会有15人参加.所以像这样的快速功能会起作用..

(define (attendees ticket-price)
  (+ 120 (* (/ (- 5.00 ticket-price) 0.10) 15)))
Run Code Online (Sandbox Code Playgroud)

但是,这会返回(相当讨厌)..

> (attendance 4.90)
 => 134.99999999999994
Run Code Online (Sandbox Code Playgroud)

所以在尝试了教科书中的(几乎完全相同的)解决方案之后......

(define (attendance price)
  (+ (* (/ 15 .10) (- 5.00 price))
    120))
Run Code Online (Sandbox Code Playgroud)

我得到了完全相同的错误.这是我的本地系统特有的吗?我很好奇 - 实际上我可以简单地使用某种形式的舍入来纠正这个问题; 但我宁愿知道它为什么会先发生!

除此之外,我建议任何对Lisp感兴趣的人都要关注HTDP.它看起来是一个非常温和的文字,从略读,非常亲自动手.我喜欢SICP - 但这更像是一件长期的事情; 我似乎花了几天时间阅读,然后是练习,然后在网上赶上讲座.HTDP似乎有点像' 哦,我有15分钟的备用 - 我会看看HTDP '.

Tim*_*Tim 6

浮点数并不总是存储为您期望的确切值.参见例如浮点的危险.

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

(define (attendees ticket-price-cents)
  (+ 12000 (* (/ (- 500 ticket-price-cents) 10) 1500)))
Run Code Online (Sandbox Code Playgroud)

  • 并且要更清楚:在Racket中,如果键入`0.25`,如果为其配置了基础语言级别,它将完全读取**.HTDP中使用的初学者语言水平与其他学生语言水平一样,旨在实现此目的.否则,在专业级的Racket(`#lang racket`)中,你会更明确地写出精确的小数:`#e0.25`. (2认同)

Joh*_*nts 5

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

JFYI!