精度误差问题与eps

简介: 精度误差问题与eps

前言

对于精度误差这个词的认识是在看别人写的sqrt函数应用时开始的,现在并没有在这方面遇到过问题,下面的经验是对所看过这一类文章的总结


一、什么是精度误差

比如这里我们用一个double去接收一个六位精度的值,那么前六位数的值一定是固定的,但是六位以后的值由于没有固定的输入将会是任意可能出现的数值。同理我们如果存入0给double在0以后位数的值也都是不确定的,这种不确定位数的值不可控的现象就是精度误差。

二、精度误差事例即解决方法

1、sqrt判断质数

一般的判断质数的代码都是如下的,我一开始也是这么写的。

1. bool find(int n)
2. {
3.  for(int i=2;i<=sqrt(n);i++)
4.  {
5.    if(n%i==0)
6.      return false;
7.  }
8.  return true;
9. }

但这样的写法其实是不严谨的,比如说我判断9是不是素数,这时候sqrt(9)的值本应该是3,但其实sqrt的返回值是一个浮点数,所以这里的精度误差就可能导致返回值为2.9999999这一类数,从而导致答案的错误,正确的写法应该如下。

1. bool find(int n)
2. {
3.  int sql=(int)sqrt(1.0*n);//1.0*n的目的是  隐式转换成浮点数,开根号后再强制转换成整型 
4.  for(int i=2;i<=sql;i++)
5.  {
6.    if(n%i==0)
7.      return false;
8.  }
9.  return true;
10. }

2、判断浮点数相等

即使是理论上相同的值,由于是经过不同的运算过程得到的,他们在低几位有可能(一般来说都是)是不同的。这种现象看似没太大的影响,却会一种运算产生致命的影响: ==。注意,C/C++中浮点数的==需要完全一样才能返回true,解决的办法是引进eps,来辅助判断浮点数的相等。

eps缩写自epsilon,表示一个小量,但这个小量又要确保远大于浮点运算结果的不确定量。eps最常见的取值是1e-8左右。引入eps后,我们判断两浮点数a、b相等的方式如下

这样,我们才能把相差非常近的浮点数判为相等;同时把相差较大(差值大于eps)的数判为不相等。

3、eps解决函数越界

如果sqrt(a), asin(a), acos(a) 中的a是你自己算出来并传进来的,那么就有可能因为浮点误差导致出现错误。如果a本来应该是0的,由于浮点误差,可能实际存储的是一个绝对值很小的负数(比如1e-12),这样sqrt(a)应得0的,直接因a不在定义域而出错。

类似地,如果a本来应该是±1,则asin(a)、acos(a)也有可能出错,对于此种函数,必需事先对a进行校正。

4、eps解决输出问题

这一节都是因为题目要求输出浮点数导致的问题,并且都和四舍五入有关。

现在考虑一种情况,题目要求输出保留两位小数。case的正确答案的精确值是0.005,按理应该输出0.01,但你的结果可能是0.005000000001(恭喜),也有可能是0.004999999999(悲剧),如果按照printf(“%.2lf”, a)输出,那你的遭遇将和括号里的字相同。

解决办法是如果a为正,则输出a+eps, 否则输出a-eps

5、 输入值波动过大

假如一道题输入给一个浮点数a, 1e-20 < a < 1e20。这时候就不要再用1e-8左右作为eps的值了,合理的做法是把eps按照输入规模缩放到合适大小。


总结

在对set进行判重的时候,是不是用==来判重的?经观察,set不是通过==来判断相等的,是通过<来进行的,具体说来,只要a<b 和 b<a 都不成立,就认为a和b相等,可以发现,精度误差问题可以用这个方法或者eps很好的解决的。容易产生较大浮点误差的函数有asin、 acos,所以尽量使用atan2。另外,如果数据明确说明是整数,而且范围不大的话,使用int或者long long代替double都是极佳选择.

相关文章
|
7月前
QAM 归一化因子
QAM 归一化因子
160 0
|
7月前
|
机器学习/深度学习
FFT能量归一化
FFT能量归一化
149 0
|
C++
深度解析roc曲线、AUC与排序损失
深度解析roc曲线、AUC与排序损失
209 0
|
7月前
Gamma校正
下面是自己所整理的一些gamma校正的东西如有侵权请联系删除。
65 0
|
分布式计算 搜索推荐 数据库
准确率(Accuracy) 精确率(Precision) 召回率(Recall)和F1-Measure(精确率和召回率的调和平均值)
准确率(Accuracy) 精确率(Precision) 召回率(Recall)和F1-Measure(精确率和召回率的调和平均值) Spark 构建分类模型
1832 0
准确率(Accuracy) 精确率(Precision) 召回率(Recall)和F1-Measure(精确率和召回率的调和平均值)
|
算法 数据库 计算机视觉
舌象图片自适应调节——gamma校正算法(五)
舌象图片自适应调节——gamma校正算法(五)
308 0
|
机器学习/深度学习 并行计算 算法
激活函数Relu对精度和损失的影响研究
激活函数Relu对精度和损失的影响研究
160 0
|
机器学习/深度学习 传感器 算法
【图像重建】基于离散余弦变换DCT图像重建含MSE、PSNR、压缩比附matlab代码
【图像重建】基于离散余弦变换DCT图像重建含MSE、PSNR、压缩比附matlab代码
|
传感器 监控
ABB PFEA111-65 线性传递函数斜率的误差
ABB PFEA111-65 线性传递函数斜率的误差
80 0
ABB PFEA111-65 线性传递函数斜率的误差
|
Python
Python编程:方差、标准差、均方差、均方根值、均方误差、均方根误差
Python编程:方差、标准差、均方差、均方根值、均方误差、均方根误差
334 0
Python编程:方差、标准差、均方差、均方根值、均方误差、均方根误差