由浮子组成的联盟:完全疯狂的输出

时间:2010-08-05 20:32:14

标签: c++ c floating-point unions

#include <stdio.h>

union NumericType
{
    float value;
    int intvalue;
}Values;

int main()
{
    Values.value = 1094795585.00;
    printf("%f \n",Values.value);
    return 0;
}

该程序输出为:

1094795648.000000 

任何人都可以解释为什么会这样?为什么浮动Values.value的值会增加?或者我在这里遗漏了什么?

7 个答案:

答案 0 :(得分:26)

首先,这与使用union没有任何关系。

现在,假设你写道:

int x = 1.5;
printf("%d\n", x);

会发生什么? 1.5不是整数值,因此它将转换转换为整数(通过截断)和x,因此实际获得值1,这正是打印出来。

您的示例中发生了同样的事情。

float x = 1094795585.0;
printf("%f\n", x);

1094795585.0不能表示为单个精度浮点数,因此它将转换转换为可表示的值。这通过四舍五入发生。两个最接近的值是:

1094795520 (0x41414100) -- closest `float` smaller than your number
1094795585 (0x41414141) -- your number
1094795648 (0x41414180) -- closest `float` larger than your number

因为您的数字稍微接近较大的值(如果您查看十六进制表示,这会更容易看到),它会舍入到该值,因此这是存储在x中的值,并且是打印的值。

答案 1 :(得分:14)

float并不像您希望的那样精确。其有效24位的尾数仅提供7-8个十进制数字的精度。您的示例需要10位十进制数字。 double有一个有效的53位尾数,提供15-16位精度,足以满足你的目的。

答案 2 :(得分:7)

这是因为您的float类型没有显示该数字的精确度。使用double

答案 3 :(得分:2)

浮点数只有7位精度 有关详细信息,请参阅此链接: link text

当我这样做时,我得到相同的结果:

int _tmain(int argc, _TCHAR* argv[])
{
    float f = 1094795585.00f; 
    //        1094795648.000000
    printf("%f \n",f); 
    return 0; 
}

答案 4 :(得分:1)

我根本不明白为什么人们使用花车 - 它们通常不比双打快,而且速度可能更慢。这段代码:

#include <stdio.h>

union NumericType
{
    double value;
    int intvalue;
}Values;

int main()
{
    Values.value = 1094795585.00;
    printf("%lf \n",Values.value);
    return 0;
}

产生

1094795585.000000

答案 5 :(得分:0)

默认情况下,带有%f的float的printf将在小数点后给出精度6。如果要在小数点后使用%.2f的精度为2位数。 即便如下,也会给出相同的结果

#include <stdio.h>
union NumericType
{
    float value;
    int intvalue;
}Values;

int main()
{
    Values.value = 1094795585;
    printf("%f \n",Values.value);
    return 0;
}

Result 
./a.out
1094795648.000000

答案 6 :(得分:0)

这只会使十进制数字变得复杂,因为这是二进制算术。为了解释这一点,我们可以从单精度格式的整数集开始,其中所有整数都是可表示的。由于单精度格式具有23 + 1 = 24位精度,这意味着范围是

0 to 2^24-1

这对于解释不够好或不够详细,所以我会进一步完善它

0 to 2^24-2^0 in steps of 2^0

下一个更高的集是

0 to 2^25-2^1 in steps of 2^1

下一个较低的设置是

0 to 2^23-2^-1 in steps of 2^-1

您的号码,1094795585(十六进制为0x41414141),落在最大值略小于2 ^ 31 =的范围内。该范围可以以2 ^ 7的步长详细表示为0到2 ^ 31-2 ^ 7。这是合乎逻辑的,因为2 ^ 31是2的大于24的7次幂。因此,增量也必须是2次幂的7次幂。

查看另一篇文章中提到的“下一个较低”和“下一个较高”的值,我们看到它们之间的差异是128 i e 2 ^ 7.

这真的没有什么奇怪或奇怪或有趣甚至魔力。它实际上非常清晰而且非常简单。