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 |
有人能解释为什么会这样吗?为什么浮动汇率增加了?还是我在这里丢了什么?
首先,这与使用
现在,假设你写:
1 2 3 | int x = 1.5; printf("%d ", x); |
会发生什么?
在您的示例中发生了完全相同的事情。
1 2 3 | float x = 1094795585.0; printf("%f ", x); |
1 2 3 | 1094795520 (0x41414100) -- closest `float` smaller than your number 1094795585 (0x41414141) -- your number 1094795648 (0x41414180) -- closest `float` larger than your number |
因为您的数字稍微接近较大的值(如果您查看十六进制表示形式,这会比较容易看到),所以它舍入到该值,因此这是存储在
浮点数并不像你希望的那样精确。其24位有效尾数仅提供7-8位小数的精度。您的示例需要10位十进制数字的精度。双精度数有一个有效的53位尾数,它提供15-16位的精度,这足以满足您的需要。
这是因为您的
浮点数只有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 |