Possible Duplicate:
Floating point comparison
我对 C/C++ 中 float 的准确性有疑问。当我执行下面的程序时:
#include <stdio.h>
int main (void) {
float a = 101.1;
double b = 101.1;
printf ("a: %f\n", a);
printf ("b: %lf\n", b);
return 0;
}
结果:
a: 101.099998
b: 101.100000
我相信 float 应该有 32 位,所以应该足以存储 101.1 为什么?
你只能在 IEEE754 中准确地表示数字(至少对于单精度和 double 二进制格式),如果它们可以通过将两个的倒幂相加来构造(即 2<sup>-n</sup>
,如 1
、1/2
、1/4
、1/65536
等) 取决于可用于精度的位数。
在 float (23 位精度)或 double (52 位精度)提供的缩放范围内,没有两个的倒幂的组合可以使您精确到 101.1。 p>
如果您想快速了解二次幂倒数的工作原理,请参阅 this answer。
将该答案中的知识应用于您的 101.1
数字(作为单精度 float ):
s eeeeeeee mmmmmmmmmmmmmmmmmmmmmmm 1/n
0 10000101 10010100011001100110011
| | | || || || |+- 8388608
| | | || || || +-- 4194304
| | | || || |+----- 524288
| | | || || +------ 262144
| | | || |+--------- 32768
| | | || +---------- 16384
| | | |+------------- 2048
| | | +-------------- 1024
| | +------------------ 64
| +-------------------- 16
+----------------------- 2
尾数部分实际上一直持续到 101.1
:
mmmmmmmmm mmmm mmmm mmmm mm
100101000 1100 1100 1100 11|00 1100 (and so on).
因此这不是精度问题,没有多少有限位可以准确地表示 IEEE754 格式的数字。
使用位来计算实际 数(最接近的近似值),符号为正。指数为 128+4+1 = 133 - 127 偏差 = 6,因此乘数为 26 或 64。
尾数由 1(隐式基数)加上(对于所有那些每个值都为 1/(2n) 的位组成,因为 n 从 1 开始并向右递增),{1/2, 1/16, 1/64, 1/1024, 1/2048, 1/16384, 1/32768, 1/262144, 1/524288, 1/4194304, 1/8388608}
。
当你将所有这些加起来,你会得到 1.57968747615814208984375
。
当您将其乘以先前计算的乘数 64
时,您将得到 101.09999847412109375
。
所有数字都是使用 bc
使用 100 位十进制数字的比例计算的,导致很多尾随零,因此数字应该非常准确。双重如此,因为我检查了结果:
#include <stdio.h>
int main (void) {
float f = 101.1f;
printf ("%.50f\n", f);
return 0;
}
也给了我 101.09999847412109375000...
。