c 中%f说明符的不可预知行为

使用以下代码:

float f = 23.456; printf("%f", f); 

不同f值的输出是:

  Value Output --------- -------- f = 23.456 23.455999 f = 23.956 23.955999 f = 23.947 23.947001 f = 23.656 23.656000 

为什么价值不可预测或有模式?

这是因为C使用IEEE 754 32位浮点格式来存储浮点数。 您拥有的尾数以二进制forms转换,并存储在float变量所需的低位23位4字节空间中。 有时它可以完全转换为精确的二进制,有时它可能没有完全转换,因此存储了数字的截断forms,这是从内存中读取时,评估为稍微不同的值。

此行为类似于数学,您使用1/3值作为0.33或0.333,具体取决于您的精度要求。

尝试使用:
f = 0.25; 要么,
f = -15.625; 或者,任何十进制值可以完全转换为二进制,您将得到正确的结果。

这属于每个程序员应该知道浮点数的类别。 浮点的工作方式意味着某些数字在浮点中不能完全表示。 解释这个的最简单方法是要求你将值1/3写为十进制数。 你开心得很愉快,但最终你最终没纸了。 其原因在于,在十进制表示法中,数字1/3是无限长的,因此在使用十进制表示法来存储数字的合理编码系统中,它可以存在多长时间。

浮点做同样的事情,但使用基数2.这意味着我们看起来非常简单的数字,例如1/10或0.1,变得无限递归。 当您打印数字时,这会导致舍入错误,因为您存储的数字不是您给编译器的数字,因为无法存储该数字。

关于这个的规范性论文是http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html ,这是一个很大的读物,但解释了所有这些以及更多。

使用floatdouble您可以使用一定的位来表示计算机中的数字x 。 对于float它通常是32位, double是64位。

结果呢? 您只能在float存储2 ^ 32个不同的数字,在double float数中存储2 ^ 64个数字。 由于存在无限量的“其他”数字,这意味着这些数字无法表示。 但人们仍然希望使用这些数字(关于数字不可用的编译器错误会很奇怪,不是吗?)。 因此,选择接近 x的数字。 在大多数应用程序中,这是“足够接近”。 但出于同样的原因:永远不要相信float ,即永远不要试图问“是x = 5?”。