浮点数比较问题

71 篇文章 2 订阅

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            //f1与f2相同 not same         //g与d不同
f1与f2的前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 例:求一元二次方程的解
 a=0 不是二次方程,是一次方程  b2-4ac=0 有两个相等实根  b2-4ac>0 有两个不等实根  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; 

 }

 }  

 } 


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值