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

相关文章
|
消息中间件 缓存 NoSQL
Redis经典问题:缓存雪崩
本文介绍了Redis缓存雪崩问题及其解决方案。缓存雪崩是指大量缓存同一时间失效,导致请求涌入数据库,可能造成系统崩溃。解决方法包括:1) 使用Redis主从复制和哨兵机制提高高可用性;2) 结合本地ehcache缓存和Hystrix限流降级策略;3) 设置随机过期时间避免同一时刻大量缓存失效;4) 使用缓存标记策略,在标记失效时更新数据缓存;5) 实施多级缓存策略,如一级缓存失效时由二级缓存更新;6) 通过第三方插件如RocketMQ自动更新缓存。这些策略有助于保障系统的稳定运行。
1026 1
|
负载均衡 关系型数据库 RDS
良好架构设计中的可靠性:高可用、容错、灾难恢复
良好架构设计支柱 云计算良好架构设计有五大支柱,分别是:安全性,可靠性,性能效率,成本优化和卓越操作。其中可靠性是指系统从基础设施或者服务故障当中实现恢复、以动态方式获取计算资源以满足需求,以及缓解配置错误或者暂时性网络问题等干扰因素的能力。
5256 0
|
Ubuntu 安全 网络协议
|
9月前
|
数据采集 存储 消息中间件
构建高效数据管道:从数据采集到分析的实战指南
在数据的海洋中航行,我们需要精准而高效的工具来捕捉、传输和处理信息。本文将引导你穿越技术性文章的迷雾,用简洁明了的语言和代码示例,展现如何打造一个高性能的数据管道。无论你是初学者还是资深开发者,这篇文章都将为你提供宝贵的知识财富。让我们一起解锁数据的力量,探索其背后的奥秘。
252 15
|
9月前
|
存储 JSON 开发工具
三、HarmonyOS NEXT应用开发:ArkTS工程目录结构(Stage模型)
本文介绍了HarmonyOS NEXT应用开发中ArkTS工程的目录结构(Stage模型),包括AppScope、entry、hvigor、oh_modules等主要目录及其作用。重点解析了entry目录下的src > main > resources目录结构,详细说明了base、限定符目录和rawfile的作用,以及如何引用资源文件。
470 1
|
12月前
|
程序员 编译器
C 标准库 - <float.h>详解
`&lt;float.h&gt;` 是 C 标准库中的头文件,用于定义浮点数的属性和限制,包括有效数字位数(如 `FLT_DIG`)、最小最大值(如 `FLT_MIN` 和 `FLT_MAX`),以及特殊值(如 `FLT_INFINITY`)。它通过提供一系列常量和宏帮助程序员处理浮点运算的范围和精度问题。
|
数据采集 Web App开发 JavaScript
Python 网络爬虫技巧分享:优化 Selenium 滚动加载网易新闻策略
Python 网络爬虫技巧分享:优化 Selenium 滚动加载网易新闻策略
|
数据处理
时间序列分析实战(一):时序平稳性和白噪声检验
时间序列分析实战(一):时序平稳性和白噪声检验
|
SQL Java 关系型数据库
JavaWeb(JDBC编程)看这一篇就够了 —— 如何使用Java操作mysql数据库
JavaWeb(JDBC编程)看这一篇就够了 —— 如何使用Java操作mysql数据库
474 0
|
C语言
【C语言】柔性数组(可变长数组)
【C语言】柔性数组(可变长数组)