再次浮点精度

joh*_*ohn 5 c floating-point floating-accuracy ieee-754 floating-point-precision

昨天我问一个问题,为什么我是在一个浮点运算精度损失.我收到一个关于如何在x87寄存器中保存中间结果的答案.这很有帮助,但有些细节仍在逃避.这是我在上一个问题中提出的程序的变体,我在调试模式下使用VC++ 2010 Express.

int main()
{
    double x = 1.8939201459282359e-308; /* subnormal number */
    double tiny = 4.9406564584124654e-324; /* smallest IEEE double */
    double scale = 1.6;
    double temp = scale*tiny;
    printf("%23.16e\n", x + temp);
    printf("%23.16e\n", x + scale*tiny);
}
Run Code Online (Sandbox Code Playgroud)

这输出

1.8939201459282369e-308
1.8939201459282364e-308
Run Code Online (Sandbox Code Playgroud)

根据IEEE标准,第一个值是正确的.赋予scale变量值2.0可为两种计算提供正确的值.据我所知,temp在第一次计算中是一个次正规值,因此失去了精度.我也理解,值scale*tiny保存在x87寄存器中,该寄存器具有更大的指数范围,因此该值具有更高的精度temp.我不明白的是,在添加值时,x我们从较低的精度值中得到正确的答案.当然,如果较低的精度值可以给出正确的答案,那么更高的精度值也应该给出正确的答案吗?这与"双舍入"有关吗?

在此先感谢,这对我来说是一个全新的主题,所以我有点挣扎.

Dan*_*her 7

关键在于,由于指数范围较大,这两个数字在x87表示中不是次正规的.

在IEEE754表示中,

x    = 0.d9e66553db96f × 2^(-1022)
tiny = 0.0000000000001 × 2^(-1022)
Run Code Online (Sandbox Code Playgroud)

但在x87表示中,

x    = 1.b3cccaa7b72de × 2^(-1023)
tiny = 1.0000000000000 × 2^(-1074)
Run Code Online (Sandbox Code Playgroud)

现在,当1.6*tiny在IEEE754表示中计算时,它被舍入到0.0000000000002 × 2^(-1022)因为这是与数学结果最接近的可表示的数字.将其添加到x结果中

  0.d9e66553db96f × 2^(-1022)
+ 0.0000000000002 × 2^(-1022)
-----------------------------
  0.d9e66553db971 × 2^(-1022)
Run Code Online (Sandbox Code Playgroud)

但是在x87表示中,1.6*tiny变成了

1.999999999999a × 2^(-1074)
Run Code Online (Sandbox Code Playgroud)

当它被添加

  1.b3cccaa7b72de × 2^(-1023)
+ 0.0000000000003333333333334 × 2^(-1023)
-----------------------------------------
  1.b3cccaa7b72e1333333333334 × 2^(-1023)
Run Code Online (Sandbox Code Playgroud)

结果四舍五入为53位有效位

  1.b3cccaa7b72e1 × 2^(-1023)
Run Code Online (Sandbox Code Playgroud)

使用有效数字1中的最后一位.如果然后将其转换为IEEE754表示(其中有效数据中最多可以包含52位,因为它是一个次正规数),因为它恰好位于两个相邻可表示数字之间的中间位置0.d9e66553db970 × 2^(-1022),0.d9e66553db971 × 2^(-1022)它是默认情况下舍入为有效数字为零的最后一位.

请注意,如果FPU未配置为仅使用53位有效数字,而是使用x87扩展精度类型的完整64位,则添加的结果将更接近IEEE754结果0.d9e66553db971 × 2^(-1022),因此舍入到该值.

实际上,由于x87表示具有较大的指数范围,因此即使在有效数字中的位数有限,IEEE754-次正规数的有效数也比IEEE754表示更多.因此,计算结果在x87中比IEEE754中有一个更重要的位.