现在的位置: 首页 > 综合 > 正文

浮点数的比较问题,不能直接比较,需用精度

2013年08月31日 ⁄ 综合 ⁄ 共 3153字 ⁄ 字号 评论关闭

浮点数比较问题

1、直接进行关系比较的错误(==

浮点数可以进行比较,但是由于不同浮点类型中表示精度的差异,所以会引起一些错误。

1
:

#include <iostream.h>

void main()

{

       float
f1=7.123456789;

float f2=7.123456787;

cout<<(f1!=f2?”not same/n”:”same/n”);   

float g=1.0/3.0;

double d=1.0/3.0;

cout<<(g = =d?”same/n”:”not same/n”);

}

运行结果:

same            //f1f2相同

not same         //gd不同

f1f2的前6位有效数位相等而后面的数不同,在计算机中可能被表示为同一个数。因float型精度有限,不能分辨其差异,造成判断有误(认为是相同的数)。解决的方法是使用double型数据。

2

#include <iostream.h>

#include <math.h>

#include <iomanip.h>

void main()

{

double d1=123456789.9*9;

double d2=1111111109.1;

cout<<(d1==d2?"
same/n":"not same/n");   

cout<<
((fabs(d1-d2)<1e-6)?"same/n":"not same/n");

cout<<setprecision(9);

cout<<setiosflags(ios::fixed)<<d1<<"/n"<<d2<<"/n";

}

运行结果:

not same

same

1111111109.100000143

1111111109.099999905

2、使用浮点数进行相等(==)和不相等(!=)比较的操作通常是有问题的。浮点数的相等比较,一般用两者相减的值是否落在0的邻域中来判断。

3、测试一个浮点值与零的关系也存在误差。

在林锐的<<高质量C/C++编程>>中提到:不可将浮点变量用“==”或“!=”与任何数字比较。原因是有精度限制。应该转换成以下形式  

 
if   ((x>=-EPSINON)   &&  
(x<=EPSINON))  

 
其中EPSINON是允许的误差(即精度)。 

浮点数与0的比较:

 之所以要这样if(fabs(i)<=1e-6),是因为对于一个数,在数学上,只要这个数小于一个任意小的正数,我们就可以说这个数等于零。这是与极限相关的一个概念。如果想深入了解为什么,可以看看数学分析。  
 
所以,在计算机编程时,我们之所以用这样的方法来比较实型,是因为这样可以任意达到所需的精度,也就是说fabs(i)可以小于更大或者更小的一个数来达到确认是否等于零的目的。

浮点数与零的比较:

等于0关系:  fabs(i)<=1e-6

大于0关系:  i>1e-6

小于0关系:  i<1e-6

例:求一元二次方程的解

l 
a=0
不是二次方程,是一次方程

l 
b2-4ac=0
有两个相等实根

l 
b2-4ac>0
有两个不等实根

l 
b2-4ac<0
有两个共轭复根

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

//c代码

#include <stdio.h>

#include <math.h>

main( )

{ 

       double
a,b,c,disc,x1,x2,realpart,imagpart;

   
printf("
请输入a,b,c:");

   
scanf("%lf%lf%lf",&a,&b,&c);

   
if(fabs(a)<=1e-6)  

              printf("不是2次方程, 1次方程/n");

    else

    {

              disc=b*b-4*a*c;

              if(fabs(disc)<=1e-6)

                     printf("有两个相等的实根%f",(-b/(2*a)));

              else  if(disc>1e-6)

              {

                     x1=(-b+sqrt(disc))/(2*a);

            x2=(-b-sqrt(disc))/(2*a);

                     printf("有两个不等的实根:/n");

                     printf("x1=%f/n",x1);

                printf("x2=%f/n",x2);

              }

              else

              {

                     realpart=-b/(2*a);

                     imagpart=sqrt(-disc)/(2*a);

                     printf("有两个复根:/n");

                  printf("%f+%fi/n",realpart,imagpart);

                  printf("%f-%fi/n",realpart,imagpart);

              }

       }  

}

 

 

 

 

 

 

 

 

 

 

 

//C++代码

#include <iostream.h>

#include <math.h>

#include <iomanip.h>

void   main( )

{ 

       double
a,b,c,disc,x1,x2,realpart,imagpart;

   
cout<<"
请输入a,b,c:";

   
cin>>a>>b>>c;

   
if(fabs(a)<=1e-6)  

              cout<<"不是2次方程,
1次方程/n";

   
else

   
{

              disc=b*b-4*a*c;

              if(fabs(disc)<=1e-6)

                     cout<<"有两个相等的实根:"<<(-b/(2*a));

              else  if(disc>1e-6)

              {

                     x1=(-b+sqrt(disc))/(2*a);

            x2=(-b-sqrt(disc))/(2*a);

                     cout<<"有两个不等的实根:/n";

                     cout<<setprecision(5)<<"x1="<<x1<<endl;

                     cout<<setprecision(5)<<"x2="<<x2<<endl;

              }

              else

              {

                     realpart=-b/(2*a);

                     imagpart=sqrt(-disc)/(2*a);

                     cout<<"有两个复根:/n";

                     cout<<setprecision(5)<<realpart<<"+"<<imagpart<<"i"<<endl;

                     cout<<setprecision(5)<<realpart<<"-"<<imagpart<<"i"<<endl;

              }

       }  

}

 

 

抱歉!评论已关闭.