网格步长(两个相邻的机器可表示数字之间的差异

Grid step (difference between two adjacent machine-representable numbers

我写了这样一段代码来求网格步长(两个相邻机器可表示数之间的差,机器epsilon大于一和一的最小机器可表示数之间的差)。为什么这个程序对于很大的 x 值显示 1 以及如何修复它以显示正确答案?

#include <stdio.h>
int main(void)
{
    long double x,eps=1.0,a; 
    scanf("%Lg",&x);
    do
    {
        a=eps;
        eps/=2.0;
    }
    while( x+eps>x);
    printf("Grid step: %Le",(long double)a);
    return 0;
}

浮点数表示为符号(+1 或 −1)s、指数 e 和数字f 在固定基数(称为尾数)中具有固定位数。以底数b和精度(位数)p,用符号s表示的数,指数e, 和数字 f0, f−1, f−2, f−3, f−4,…f 1−psbe•sum(fibi 因为 −p < i ≤ 0)。

例如,底数2,精度4,符号+1,指数1,尾数1.001,表示的数为+1•21•1.0012 = 2•1⅛ = 2¼ = 9/4 = 2.25.

给定范围内的任何可表示数,通过将 1 加到有效数的最低位来获得下一个更大的可表示数。在上面的示例中,下一个更大的数将具有有效数 1.010 以及相同的符号和指数,因此它将是 +1•21•1.0102 = 2•1¼ = 2½ = 10/4 = 2.5.

这意味着,如果一个数字x用指数e表示,那么它与下一个更大的可表示数字之间的差是beb1−p = be+1−p .

数字1用指数0表示,因为1 = +1•b0•1.000…000b。所以 1 和下一个可表示数之间的差是 b1−p。如果您的 long double 格式的基数为 2,精度为 64 位,则此差值为 21−64 = 2−63 ,所以所谓的“机器epsilon”的值应该是2−63.

如果使用二进制格式,则 2 的指数为 1,因此它与下一个可表示数字之间的差值为 b e+1−p = 21+1−64 = 2−62。这些差异称为 ULP,最小精度单位。

4的ULP为2−61,8的ULP为2−60,依此类推。对于 263,ULP 为 263−63 = 1.

当您输入 264 或更大的数字时,您的程序无法找到 ULP,因为 ULP 大于 1,但您的程序开始查找 1 和向下工作。

您可以通过从 long double 格式中尽可能大的 ULP 开始,或者根据 x 的值将程序更改为向上或向下工作来修复它。