精度误差问题与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都是极佳选择.

相关文章
|
开发框架 编译器 C语言
外部依赖项、头文件、源文件、资源文件
外部依赖项、头文件、源文件、资源文件
551 0
|
负载均衡 关系型数据库 RDS
良好架构设计中的可靠性:高可用、容错、灾难恢复
良好架构设计支柱 云计算良好架构设计有五大支柱,分别是:安全性,可靠性,性能效率,成本优化和卓越操作。其中可靠性是指系统从基础设施或者服务故障当中实现恢复、以动态方式获取计算资源以满足需求,以及缓解配置错误或者暂时性网络问题等干扰因素的能力。
5360 0
|
6月前
|
安全 Java API
2025 年 Java 校招面试常见问题及详细答案汇总
本资料涵盖Java校招常见面试题,包括Java基础、并发编程、JVM、Spring框架、分布式与微服务等核心知识点,并提供详细解析与实操代码,助力2025校招备战。
344 1
|
程序员 编译器
C 标准库 - <float.h>详解
`&lt;float.h&gt;` 是 C 标准库中的头文件,用于定义浮点数的属性和限制,包括有效数字位数(如 `FLT_DIG`)、最小最大值(如 `FLT_MIN` 和 `FLT_MAX`),以及特殊值(如 `FLT_INFINITY`)。它通过提供一系列常量和宏帮助程序员处理浮点运算的范围和精度问题。
|
前端开发
css 块元素、行内元素、行内块元素相互转换
css 块元素、行内元素、行内块元素相互转换
748 0
|
数据采集 Web App开发 JavaScript
Python 网络爬虫技巧分享:优化 Selenium 滚动加载网易新闻策略
Python 网络爬虫技巧分享:优化 Selenium 滚动加载网易新闻策略
|
数据处理
时间序列分析实战(一):时序平稳性和白噪声检验
时间序列分析实战(一):时序平稳性和白噪声检验
GDAL使用PROJ坐标转换相关问题的总结
GDAL使用PROJ坐标转换相关问题的总结
413 0
|
人工智能 前端开发 UED
1分钟解锁属性:HTML中的列表标签属性
1分钟解锁属性:HTML中的列表标签属性
|
安全 Java 调度
Python创建和结束线程
【7月更文挑战第1天】 - 启动线程:`thread.start()`,等待线程:`thread.join()`。 - 无法直接结束线程,通常通过设置标志位(如全局变量`is_running`)让线程自行退出。 - 使用`Event`对象(`stop_event.is_set()`)提供安全的线程结束方式。 - 异常处理:`try-except`捕获线程中异常,避免意外终止。

热门文章

最新文章