【问题标题】:IEEE754 float point substraction precision lostIEEE 754 浮点减法精度丢失
【发布时间】:2015-07-28 20:54:40
【问题描述】:

这是减法

第一个数字

Decimal       3.0000002
Hexadecimal   0x4040001
Binary: Sign[0], Exponent[1000_0000], Mantissa[100_0000_0000_0000_0000_0001]

减去第二个数字:

Decimal 3.000000
Hexadecimal 0x4040000
Binary: Sign[0], Exponent[1000_0000], Mantissa[100_0000_0000_0000_0000_0000]

============================================

在这种情况下,指数已经相同,我们只需要减去尾数。我们知道在 IEEE754 中,尾数前面有一个隐藏位 1。因此,结果尾数应该是:

Mantissa_1[1100_0000_0000_0000_0000_0001] - Mantissa_2[1100_0000_0000_0000_0000_0000]

等于

Mantissa_Rst = [0000_0000_0000_0000_0000_0001]

但是这个数字没有归一化,因为第一个隐藏位不是 1。因此我们将 Mantissa_Rst 右移 23 次,同时指数减 23。

那么我们就有了结果值

Hexadecimal 0x4040000

Binary: Sign[0], Exponent[0110_1000], Mantissa[000_0000_0000_0000_0000_0000].

总共 32 位,不需要四舍五入。

注意在尾数区域,还有一个隐藏的1。

如果我的计算是正确的,那么将结果转换为十进制数是0.00000023841858,与实际结果0.0000002相比,我仍然认为这不是很精确。

所以问题是,我的计算错了吗?或者实际上这是一个真实的情况,并且一直在计算机中发生?

【问题讨论】:

  • 十进制数3.0000002不能以2为底精确表示,它将四舍五入到最接近的可表示数字。将其转换为双精度并输出更多数字,您就会明白我的意思了。
  • 这在计算机上一直发生。如果你想看的话。尝试计算 (1/3 + 1/3 +1/3) ==1。这是因为它可以正好是 0.0000002,尾数为 23,指数为 8
  • 如果您认为这很糟糕,请意识到这是良性取消。还有一个类似的问题,称为灾难性取消。

标签: c++ floating-point floating-accuracy floating-point-precision


【解决方案1】:

不准确已经从您的输入开始。 3.0000002 是分母中素因数为 5 的分数,因此它以 2 为底的“十进制”扩展是周期性的。没有多少尾数位足以准确地表示它。您给出的浮点数实际上具有 3.0000002384185791015625 的值(这 是 精确的)。是的,这种情况一直都在发生。

不过,不要绝望! Base 10 也有同样的问题(例如1/3)。这不是问题。好吧,它适用于某些人,但幸运的是,还有其他数字类型可以满足他们的需求。浮点数有很多优点,轻微的舍入误差与许多应用程序无关,例如当您的输入不是您感兴趣的内容的完全准确测量时(大量科学计算和模拟)。还要记住 64 位浮点数也存在。此外,误差是有界的:通过尽可能最好的舍入,您的结果将在从无限精度结果中删除的最后一位的 0.5 个单位内。对于作为示例的 32 位浮点数,这大约是 2^-25,或 3 * 10^-8。当您执行必须舍入的额外操作时,这种情况会变得越来越糟,但是通过仔细的数值分析和right algorithms,您可以从中获得很多里程。

【讨论】:

  • 那么,我的手算步骤正确吗?我的意思是,对于隐藏的 1,我不太确定我的计算步骤的方式。
  • @ShuaiyuJiang 我没有仔细看你的十六进制计算,但我没有发现它们有什么明显的问题。
  • @ShuaiyuJiang 我没有重新计算偏移量、新指数是多少等,但总体上看起来是正确的。
【解决方案2】:

只要 x/2 ≤ y ≤ 2x,x - y 的计算就是精确,这意味着没有任何舍入误差。在您的示例中也是如此。

您只是错误地假设您可以有一个等于 3.0000002 的浮点数。你不能。 “float”类型只能表示小于 2^24 的整数乘以 2 的幂。 3.0000002 不是这样的数字,因此它被四舍五入到最接近的浮点数,即更接近 3.00000023841858。减去 3 可以精确计算差值,并得出接近 0.00000023841858 的结果。

【讨论】:

    猜你喜欢
    • 2013-07-24
    • 2021-10-06
    • 2016-05-26
    • 2011-05-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-06
    • 2014-10-18
    相关资源
    最近更新 更多