我有这个简单的代码行:
float val = 123456.123456;
当我打印此val或查看范围时,它存储值123456.13
好吧,没关系,它只能在4个字节之后存储所有那些数字,但为什么它在点之后会产生13?不应该是12?
(在win32上使用vc ++ 2010 express)
答案 0 :(得分:10)
在二进制中,123456.123456是11110001001000000.000111111001 ...(无限)。它舍入到11110001001000000.001或123456.125。 那在打印时会转到123456.13。
答案 1 :(得分:8)
val
中存储的值等于123456.125
。你得到的是.13
,因为你正在围绕它:
float val = 123456.123456;
printf("%.4f %.2f\n", val, val);
输出:123456.1250 123456.13
在这种情况下,您应该使用double来避免截断。编译器也应该警告你: “警告C4305:'初始化':从'double'截断到'float'” 。
答案 2 :(得分:7)
当表示为浮点数时,您的数字的指数为16(即该值是其尾数乘以2 ^ 16或65536)。然后mantisse变成
123456.123456 / 65536 = 1.8837909462890625
为了适应32位浮点数,mantisse被截断为23位,所以它现在变为1.883791
。如果再乘以65536
,则会变为123456.125
。
请注意小数点后第三个位置的5
:您使用的C ++输出例程将其舍入,使您的最终数字看起来像123456.13
。
编辑四舍五入的解释:(瑞克里根的评论)
舍入首先以二进制(24位),十进制到二进制转换,然后到printf
的十进制。储存值为1.1110001001000000001 x 2 ^ 16 = 1.8837909698486328125 x 2 ^ 16 = 123456.125。它打印为123456.13,但只是因为Visual C ++使用“从零开始的一半”舍入。
Rick也有outstanding article on the subject。
如果您想使用其他数字及其浮动表示,则此处为very useful IEEE-754 calculator。
答案 3 :(得分:2)
尝试打印std::numeric_limits<float>::digits10
的值。这粗略地说明浮子10具有多少精度。你试图超越它,所以你正在经历精度的损失(意味着超出重要数字的数字并没有真正意义)。
答案 4 :(得分:2)
它完全依赖于编译器。在GCC中查看。它应该是xxx.12