C中类型float
的描述中提到有效位数为6
。然而,浮点类型的有效位数
float f = 12345.6;
,然后打印用printf()不打印12345.6
,它打印12345.599609
。那么对于浮点类型,“6位有效数字”(或“double
”中的“15”)意味着什么?
C中类型float
的描述中提到有效位数为6
。然而,浮点类型的有效位数
float f = 12345.6;
,然后打印用printf()不打印12345.6
,它打印12345.599609
。那么对于浮点类型,“6位有效数字”(或“double
”中的“15”)意味着什么?
根据standard,并非所有的十进制数都可以完全存储在内存中。根据表示的大小,错误可能会达到一定的最大值。对于float
这是0.0001%
(6个显著位数= 10^-6
= 10^-4 %
)。
在你的情况下,错误是(12345.6 - 12345.599609)/12345.6 = 3.16e-08
远低于浮点数的最大误差。
6个显著位数意味着该最大误差是大约+/- 0.0001%。单浮点值实际上具有大约7.2位数的精度(source)。这意味着错误大约是+/- 12345.6/10^7 = 0.0。这是你的错误的顺序(0.000391)。
这里的问题是,你不能保证一个号码都可以存储在一个浮动。你需要用尾数,基数和指数来表示这个数字,如IEEE 754所解释的那样。号码printf(...)
显示你是存储的实际浮点数。您无法确保浮点数中的多个有效数字。
你所看到的并不是真正的有意义数字的问题,但是计算机上的数字是以二进制形式存储的,而且没有3/5(= 0.6)的有限二进制表示。二进制中的3/5看起来像0.100110011001 ...,“1001”模式永远重复。这个序列相当于0.599999 ...重复。你实际上得到到小数点后三位,小数点右边的相关精密踢任何错误之前
这类似于如何有1/3没有有限基地10表示。我们有0.3333永远重复。
注意,浮点类型并不存储在基地10,所以显著*小数*数字的数量必然是一个近似值。 –
实际上有8位用于exp和23位用于压裂。 – halfelf