为什么Visual Studio 2008告诉我.9 - .8999999999999995 = 0.00000000000000055511151231257827?

rav*_*ven 8 precision immediate-window visual-studio

当我在Visual Studio 2008立即窗口中键入它时:

? .9 - .8999999999999995

它给了我这个答案:

0.00000000000000055511151231257827

文档说双精度具有15-16位精度,但是它给出了32位精度的结果.所有额外的精度来自何处?

Bar*_*own 41

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

编辑

得到一些评论之后,我现在好奇真正发生了什么.我将有问题的号码插入到这个IEEE-754转换器中.它将最后一个"27"四舍五入为"30",但我不认为这会改变结果.

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

符号:0(正)
指数:-51
有效值:1.0100000000000000000000000000000000000000000000000000(二进制为1.25 10)

所以这个数字是1.01 2 ×2 -51,或1.25 10 ×2 -51.由于只存储了三个有效的二进制数字,这表明Lars可能存在于某些东西上.它们不能是"随机噪声",因为每次转换数字时它们都是相同的.

数据表明唯一存储的数字是"5".前导零来自指数,其余看似随机的数字来自计算2 -51.

  • +1解释和使用"尾数"一词! (5认同)
  • 错误:"前导零不计数"是不正确的.答案中的15-16个重要数字是0.0000000000000005.之后的数字是不正确的,并且仅存在,因为由于前导零而将舍入误差提升为尾数.正如Barry在他的编辑中写道,结果存储为1.25*2 ^( - 51)= 5.551*10 ^( - 16),这是一个具有1位小数计算精度的数字,但是有15-16存储精度的数字. (3认同)

Lol*_*ath 17

您应该阅读:每个计算机科学家应该知道的关于浮点运算的内容 .

基本上,它归结为以有限精度存储的浮点数.你必须与一些delta进行比较.

if(.9 - .8999999999999995 <= 0.0001)
  //close enough to be equal
Run Code Online (Sandbox Code Playgroud)

  • +1:遗憾的是,对于每个浮点问题,SO无法自动回答这个问题,这是至少90%的浮点问题的正确答案. (9认同)
  • -1,不回答问题.对于双倍,q大约是32位(而不是16位). (5认同)
  • 这并没有解决他关于精确度的问题. (2认同)

Mar*_*off 14

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

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

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

  • 我倾向于这个答案,因为我认为你的答案是错误的.实际减法运算中的15-16位精度给出0.0000000000000005,其余数字是随机舍入误差.因此,在55511151231257827部分中,只有1个正确的数字,其余的是舍入误差,由于前导零而被提升为尾数.基本上,32位数是减法的16位有效数字,后加尾数中的16位噪声.存储结果后,零只会变得无关紧要. (2认同)