1

使用下面给出的 C 代码(用 Visual Studio 编写):

#include "stdafx.h"


int _tmain(int argc, _TCHAR* argv[])
{
    float i = 2.0/3.0;
    printf("%5.6f", i);
    return 0;
}

产生输出:0.666667

但是,当 %5.6f 更改为 %5.20f 时,输出更改为:0.66666668653488159000

我的问题是为什么类似小数的输出会有细微的变化?

4

5 回答 5

5

当您使用 32 位浮点数时,计算机将结果表示2./3.为 11,184,811 / 16,777,216,即 0.666666686534881591796875。在您使用的浮点数中,数字始终表示为某个整数乘以 2 的某个幂(可能是 2 的负幂)。由于整数大小的限制(使用 时float,整数必须适合 24 位,不包括符号),最接近 2/3 的可表示值是 11,184,811 / 16,777,216。

'%5.6f' 显示“0.666667”的原因printf是因为“%5.6f”只要求六位数字,所以数字在第六位四舍五入。

显示“0.66666668653488159000”的原因是您printf的实现在 17 位数字后“放弃”,从某种意义上说,这已经足够接近了。的某些实现(可能有人认为更好)会尽可能地打印所表示的值,因为所请求的格式允许。在这种情况下,它们将显示“0.66666668653488159180”,如果您请求更多数字,它们将显示精确值“0.666666686534881591796875”。%5.20fprintfprintf

(浮点格式通常以符号、1 [包括] 和 2 [不包括] 之间的分数和指数表示,而不是符号、整数和指数。在数学上,它们与指数调整:每个可以用符号、24 位无符号整数和指数表示的数字都等于某个带符号的数字、1 到 2 之间的小数以及调整后的指数。使用整数版本往往会使证明更容易,有时有助于解释。)

于 2013-06-17T15:43:56.557 回答
2

与可以以任何基数精确表示的整数不同,相对较少的小数部分具有以 2 为基数的小数格式的精确表示。

这意味着 FP 整数是精确的,而 FP 分数通常不是。

因此,对于两位数,例如 0.01 到 0.99,只有 0.25、0.50 和 0.75(和 0)具有精确表示。通常情况下,输出四舍五入并不重要,实际上,对于格式中可用的精度,几乎没有物理常数是已知的。

于 2013-06-17T15:36:23.340 回答
0

这是因为您可能没有浮点 0.6666666666666666...66667 的精确表示。

于 2013-06-17T15:30:19.233 回答
0

精度以指数格式存储,例如 (-/+)ax10^n。如果数据类型是 32 位,则将花费 1 位用于符号,8 位用于 a,其余用于 n。因此,它不会存储点后第 20 位之后的值。所以,在这个编译器中,你永远不会得到正确的值。

于 2013-06-17T15:39:36.010 回答
-1

float 类型只有 23 位来表示小数的一部分,20 太多了。

于 2013-06-17T15:40:26.440 回答