IEEE754浮点减法精度损失

时间:2015-07-28 20:54:40

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

这是减法

第一个号码

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相比,我仍然认为这不是很精确。

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

2 个答案:

答案 0 :(得分:4)

您的输入已经开始出现不准确之处。 3.0000002是分母中素数因子为5的分数,因此它的"十进制"基数2的扩张是周期性的。没有多少尾数位就足以完全代表它。您实际提供的浮点值为3.0000002384185791015625(此 确切)。是的,这种情况一直都在发生。

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

答案 1 :(得分:1)

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

您只是假设您的浮点数等于3.0000002。你不能。类型"浮动"只能表示小于2 ^ 24的整数乘以2的幂。 3.0000002不是这样的数字,因此它舍入到最接近的浮点数,更接近3.00000023841858。减法3精确计算差值并给出接近0.00000023841858的结果。