精度丢失

来源:互联网 发布:淘宝网买短款真丝旗袍 编辑:程序博客网 时间:2024/05/01 18:28

自己一直纠结于浮点类型精度丢失问题,认为浮点类型的相等比较是不靠谱的,写代码时一直不太敢用,导致了很多不必要的麻烦以及WA,所以自己研究了一下。


首先上结论,就是说浮点类型以及浮点数的比较是靠谱的,两个浮点类型,它们所表示的数的大小都是固定的,一比较,大的就大,小的就小,相等的就相等的,不会不靠谱的。浮点数同理。

不靠谱的是精度损失。比如说一个浮点数,保存在一个浮点类型里面。浮点数表示成二进制可能是无限循环小数,而浮点类型的空间又有限,所以只能截尾。所以此时保存在浮点类型里的浮点数就不是原来的那个浮点数了,这就是精度损失,这就是不靠谱。


所以说,只要不保存在浮点类型里,就不会有精度损失,就不会不靠谱。

这也就是为什么大白书P154上说“注意,f的类型是double,有可能会损失精度。解决这个问题,有一种办法是不使用中间变量”的原因了。


那什么时候可以直接比较,什么时候需要用到eps呢?

答案就是如果产生了精度损失(即曾经保存在浮点类型中过),那就最好用eps,否则就要看运气(损失后刚好一样,或者其他原因),看编译器(其实我也不知道不同的编译器会不会不同标准),看数据(如果数据很弱你就混过去了)了。


一些实用技巧:

a>=0  改为  a>-eps

a<=0  改为  a<eps


理论上我觉得UVA 10341是要用eps的,鬼知道你的1存进去后是变大了还是变小了那么一点点然后就算错了呢?

但是事实上存进去后还是1。。。所以没关系了。


一些测试代码供参考

#include<bits/stdc++.h>using namespace std;int main(){    float b=0.000001;    float a=0.000001;    if(a==0.000001) puts("YES");    else puts("NO");    if(a==b) puts("YES");    else puts("NO");    a*=1000000000000;    a/=3;    a/=2;    a/=5;    a/=7;    a/=2.71828;    a*=2.71828;    a*=7;    a*=5;    a*=2;    a*=3;    a/=1000000000000;    if(a==b) puts("YES");    else puts("NO");    a=0.000001;    a=a*1000000000000/3/2/5/7/2.71828*2.71828*7*5*2*3/1000000000000;    if(a==b) puts("YES");    else puts("NO");    return 0;}


0 0
原创粉丝点击