林锐博士在《高质量C++编程指南》中说过:“不可将浮点变量用“==”或“!=”与数字比较,应该设法转化成“>=”或“<=”此类形式”,因为那是“隐含错误的写法”。应该设法转化成下面这样的写法:
-------------------------------
const float EPSINON = 0.00001; //精度限制
if((x >= -EPSINON) && (x <= EPSINON)) //表示x为“零值”
-------------------------------
刚看到的时候没太在意,因为感觉平时编程极少会遇到要比较两个浮点值是否相等的情况。后来得空一想,又想不明白这样写为什么是错的。正巧Wayne过来串门,问他一下,结果他也不太清楚。那好吧,不知道原因,那就先写个程序试一下吧,看到底是不是错误写法:
-------------------------------
#include <iostream>
using std::cout;
using std::endl;
int main()
{
double ff = 3;
double aa = 3.6;
double tmp = aa / 1.2 - ff;
if (tmp != 0)
{
cout << "1" << endl;
}
else
{
cout << "2" << endl;
}
return 0;
}
-------------------------------
在我们看来,上面程序的输出结果应该是2的,但是很遗憾,结果是1。——我在Cygwin中用g++(gcc版本为3.4.4)测试时就是这个结果,但是用VC6.0测试时就是输出2了。可见这种写法不能保证一定正确,果然是隐含错误啊。再来试试林锐博士的办法:
-------------------------------
#include <iostream>
using std::cout;
using std::endl;
int main()
{
double ff = 3;
double aa = 3.6;
double tmp = aa / 1.2 - ff;
if (tmp < 1e-9999999999999999 && tmp > -1e-9999999999999999)
{
cout << "1" << endl;
}
else
{
cout << "2" << endl;
}
return 0;
}
-------------------------------
这下正确了。但是精度最多可以到多少呢?根据我的测试,在上面的if语句中不论写多少个“9”都不会有问题,只要不超出编译器所约束的一行中最大字符数限制就可以了。我用Cygwin中的g++(gcc版本为3.4.4)测试的时候最多写了30720个9也没有问题,不知道后面到底还可以加多少;但把这个源文件用VC6.0打开时就不行了,提示说“这个文件包含最大2048个字符的长行。行将换行。”,编译自然也是通不过的了。
现在再想想就明白前一种写法为什么不对了,在计算机组成原理中我们学过计算机对浮点数的记录和处理方法。在一系列地计算过程当中,总是少不了“对阶”的操作,这就引入了计算精度的问题。所以就有很多我们人类看着是相等的东西,给计算机看就不等了。
posted on 2008-03-12 17:13
李阳 阅读(637)
评论(0) 编辑 收藏 引用 所属分类:
C++