关于c ++:由float组成的联合:完全疯狂的输出

union consisting of float : completely insane output

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>

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

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

该程序输出为:

1
1094795648.000000

有人能解释为什么会这样吗?为什么浮动汇率增加了?还是我在这里丢了什么?


首先,这与使用union无关。

现在,假设你写:

1
2
3
int x = 1.5;
printf("%d
"
, x);

会发生什么?1.5不是一个整数值,所以它被转换成一个整数(通过截断)和x,所以实际得到的值是1,这正是打印的结果。

在您的示例中发生了完全相同的事情。

1
2
3
float x = 1094795585.0;
printf("%f
"
, x);

1094795585.0不可表示为单精度浮点数,因此转换为可表示值。这是通过舍入实现的。两个最接近的值是:

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

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


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


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


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

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

1
2
3
4
5
6
7
8
int _tmain(int argc, _TCHAR* argv[])
{
    float f = 1094795585.00f;
    //        1094795648.000000
    printf("%f
"
,f);
    return 0;
}

我只是不明白为什么人们使用浮球-他们通常不会比双打快,可能会慢。此代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>

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

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

生产:

1
1094795585.000000


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

1
0 to 2^24-1

这个不够好,也不够详细,我会进一步完善到

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

下一个更高的集合是

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

下一组是

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

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

看看另一篇文章中提到的"下一个更低"和"下一个更高"的值,我们发现它们之间的差异是128,即2^7。

这真的没有什么奇怪的,奇怪的,有趣的,甚至魔法。它实际上是绝对清晰和相当简单的。


默认情况下,带有%f的float的printf将在小数点后给出精度6。如果希望小数点后的精度为2位,请使用%.2f。即使是下面的结果也一样

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
union NumericType
{
    float value;
    int intvalue;
}Values;

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

Result
./a.out
1094795648.000000