首页 > 解决方案 > printf() 中大浮点数的奇怪行为并分配给 int

问题描述

根据我的计算,将浮点值转换为计算机存储的二进制值(符号、指数、尾数格式),在 32 位中,1 位用于符号,8 位用于指数。

所以只剩下 23 位来表示这个数字。

所以我认为具有正确行为的浮点值范围只有 0-0xffffff(基本上只有 3 个字节值),而不是 0-0xffffffff。这个对吗?

下面代码的奇怪行为是否与这个概念有关?

int main(void)
{
    float a=2555555555;
    printf("%f\n",a);
    int b = a;
    printf("%d",b);
    return 0;
}

输出:

a = 2555555584.000000
b = -2147483648

标签: cfloating-pointintprintf

解决方案


关于您的程序,首先要注意的是该值2555555555超出了(有符号的)32 位整数类型的范围。从您的程序的输出来看,您的系统上似乎int是 32 位类型,所以2555555555不能是int.

根据标准,2555555555将是 along intlong long int,这取决于是否long int足够大。

下一个相关部分是:

当整数类型的值转换为真正的浮点类型时,如果被转换的值可以在新类型中精确表示,则它是不变的。如果要转换的值在可以表示但不能精确表示的值范围内,则结果是最近的较高或最近的较低可表示值,以实现定义的方式选择。如果要转换的值超出可表示的值范围,则行为未定义。

(强调我的。)

因为2555555555需要至少 32 位尾数才能准确表示,所以它不适合 32 位float. 这就是为什么a最终包含2555555584type 的最接近的可表示值float

int b = a;本节适用:

当实浮点类型的有限值转换为除 以外的整数类型_Bool时,小数部分被丢弃(即,该值被截断为 0)。如果整数部分的值不能用整数类型表示,则行为未定义。

(强调我的。)

2555555584,所讨论的整数值,不能用带符号的 32 位 表示int。这部分代码具有未定义的行为。


推荐阅读