8

当我在 Visual Studio 2008 即时窗口中键入此内容时:

? .9 - .8999999999999995

它给了我这个答案:

0.00000000000000055511151231257827

文档说 double 具有 15-16 位精度,但它给了我一个 32 位精度的结果。所有这些额外的精度是从哪里来的?

4

6 回答 6

41

答案只有 15-16 位数字。所有这些前导零都不算数。这个数字实际上更像 5.5511151231257827 × 10 -16。尾数部分有 15-16 位数字。指数 (-16) 用于将小数点移动 16 位,但不会更改总数中的位数。

编辑

在收到一些评论后,我现在很好奇到底发生了什么。我将有问题的号码插入这个IEEE-754 Converter。冒昧地将最后的“27”四舍五入为“30”,但我认为这不会改变结果。

转换器将数字分解为三个二进制部分:

Sign: 0 (positive)
Exponent: -51
Significand: 1.0100000000000000000000000000000000000000000000000000 (binary for 1.2510)

So this number is 1.012 × 2-51, or 1.2510 × 2-51. Since there are only three significant binary digits being stored, that would suggest that Lars may be onto something. They can't be "random noise" since they are the same each time the number is converted.

The data suggests that the only stored digit is "5". The leading zeros come from the exponent and the rest of the seemingly-random digits are from computing 2-51.

于 2009-11-02T17:57:41.347 回答
17

你应该阅读:每个计算机科学家都应该知道的关于浮点运算的知识

基本上它归结为以有限精度存储的浮点数。您必须与一些增量进行比较。

if(.9 - .8999999999999995 <= 0.0001)
  //close enough to be equal
于 2009-11-02T17:39:30.963 回答
14

前导零不重要/精度的一部分(就浮点数而言 - 从数学上讲,它们重要)。前导零是由于浮点数的内部表示的指数部分。

该部分55511151231257827(即有效数或尾数)有 17 位十进制数字,足够接近 15-16 位数字。

@Lars D:您认为正确的内容仅在问题的上下文中才是正确的。 .9 - .8999999999999995计算出有效数字为 0.625 且指数为 -50 的浮点数。取 0.625 * 2 -50得到 5.5511151231257827e-16。现在,在原始问题的上下文之外,我们有一个具有 17 位有效数字的数字,恰好是我们最好的二进制近似值 0.0000000000000005。然而,就浮点数的表示而言,那些前导零仍然不重要。

于 2009-11-02T17:31:52.600 回答
4

? .9 - .8999999999999995

这个减法过程,有 15-16 个有效数字,给出

0.0000000000000005

其余数字只是舍入误差。但是,由于计算机总是在第一个非零数字之后存储 15-16 位有效数字,因此会显示舍入误差,并且您会得到大量由舍入误差产生的尾随随机数字。因此,减法运算的结果有 16 位有效数字加上存储结果的 16 位数字,即 32 位数字。

于 2009-11-02T17:37:59.233 回答
3

“浮点”的“浮动”部分意味着您正在接近 5.5511151231257827 * 10^(-16)。这并不是它的确切表示方式,因为当然这一切都是在引擎盖下以二进制形式完成的,但关键是,数字由有效数字表示,加上一个表示基数(小数点)移动多远的数字。与往常一样,维基百科可以为您提供更多详细信息:

(第二个链接更具体地关注您的特定案例。)

于 2009-11-02T17:41:01.827 回答
0

我认为这是因为在二进制系统中,5 是周期性的,因为它不能被 2 整除。然后 Mark Rushakoff 所说的适用。

于 2009-11-02T17:36:29.370 回答