1

我正在学习 c,并且很困惑,因为我的代码似乎在应该为假时将 (1e16 - 1 >= 1e16) 评估为真。我的代码在下面,它返回

9999999999999999 INVALIDBIG\n

当我希望它不会返回任何东西时。我认为使用 long long 可以避免任何大数字问题。

int main(void)
{
    long long z;

    z = 9999999999999999;

    if ( z >= 1e16 || z < 0 )
    {
        printf("%lli INVALIDBIG\n",z);
    }
}
4

2 回答 2

3

1e16 是一个双精度类型的字面值,浮点数/双精度对于十进制算术/比较可能不精确(只是许多常见示例之一:十进制 0.2)。它会将 long-long z 向上投射到两倍以进行比较,我猜标准的双精度表示不能存储所需的精度(也许其他人可以演示二进制尾数/符号表示)

尝试将 1e16 更改为 (long double)1e16,然后它不会打印出您的消息。(更新:或者,正如其他问题评论者所添加的那样,将 1e16 更改为整数文字)

于 2015-10-14T15:41:38.497 回答
1

双精度和浮点数可以容纳有限的位数。9999999999999999在您的情况下,带有值的双精度数1e16具有相同的 8 个字节的十六进制表示。您可以逐字节检查它们:

long long z = 9999999999999999;
double dz1 = z;
double dz2 = 1e16;

/* prints 0 */
printf("memcmp: %d\n", memcmp(&dz1, &dz2, sizeof(double)));

所以,他们是平等的。

较小的整数可以以完美的精度存储在 double 中。例如,请参阅双精度浮点格式可以存储在双精度中的最大整数

可以精确转换为 double 的最大整数是 2 53 ( 9007199254740992)。

于 2015-10-14T16:03:30.587 回答