随笔-4  评论-40  文章-117  trackbacks-0

林锐博士在《高质量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)测试的时候最多写了307209也没有问题,不知道后面到底还可以加多少;但把这个源文件用VC6.0打开时就不行了,提示说“这个文件包含最大2048个字符的长行。行将换行。”,编译自然也是通不过的了。

现在再想想就明白前一种写法为什么不对了,在计算机组成原理中我们学过计算机对浮点数的记录和处理方法。在一系列地计算过程当中,总是少不了“对阶”的操作,这就引入了计算精度的问题。所以就有很多我们人类看着是相等的东西,给计算机看就不等了。

posted on 2008-03-12 17:13 李阳 阅读(637) 评论(0)  编辑 收藏 引用 所属分类: C++

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理