0

在以下程序中混合使用 int 和 double 会产生一个奇怪的结果:

int main()
{
    double x = 9.90, y = 10.0, z, w;
    int    ip, fp;

    z = y - x;

    ip = (int) z;

    w = (z - ip)*100;

    printf( "\nx = %f\ty = %f\tz = %f\tw = %f\n",
            x, y, z, w );

    printf("\nip = %d", ip); /* So far, so good */

    fp = (int) w; /* Why does fp get 9 and not 10??? */

    printf("\nfp = %d\n", fp);

    return 0;
}

结果:

x = 9.900000    y = 10.000000   z = 0.100000    w = 10.000000

ip = 0
fp = 9 (Should be 10!)

结果与使用 MingGW (WinXP) e Clang (MacOSX) 相同。谁能解释这种奇怪的行为?

4

2 回答 2

1

问题是您实际上是在尝试做w = 0.1 * 1000.1 值,而浮点数不能精确表示(与1/3不能用十进制精确表示的方式相同)。

你得到的二进制 0.1 是这样的:

0.00011001100110011001100110011001100110011001100110011001...

最后 4 位数字永远重复。

虽然双精度数没有无限位数,所以它实际上是:

1.100110011001100110011001100110011001100110011001100110 * 2**(-4)

数字因为不适合而被丢弃,从“01001001 ...”开始。因为丢弃的数字以 a 开头,0所以数字将被四舍五入。这意味着您实际上最终会执行类似w = 0.9999999999 * 100.

于 2013-04-02T03:18:47.157 回答
0

出现错误是因为 adouble不能完全保持 value 9.9。它可以管理的最接近的实际上是9.9000000000000003552713678800500929355621337890625. 所以你的价值w不是10,它真的9.99999999999996447286321199499070644378662109375

当您使用%fprintf 时,它会将您的值四舍五入到小数点后 6 位。如果您将 printf 格式更改为类似的格式%.60f,您可以看到您的值的完整精度。

于 2013-04-02T03:34:33.880 回答