IO/ACM中来自浮点数的陷阱(收集向)
OI/ACM中经常要用到小数来解决问题(概率、计算几何等),但是小数在计算机中的存储方式是浮点数而不是我们在作数学运算中的数,有精度的限制。
以下以GUN C++为准,其他语言(或编译器)也差不了多少。本文竞赛向。
一、基础篇
1、一般浮点数使用double,范围为大概为-10^308 ~ 10^308,有效精度为15~16位10进制数。
2、一般没事(比如内存问题)不用float,而使用double,一个double占8个字节。
3、信息学竞赛一般使用scanf和printf输入输出,而浮点数的输入是scanf("%lf", &x),浮点数的输出是printf("%f", x),注意两个是不一样的。使用printf("%lf", x)来输出浮点数有可能会出错,因为标准中规定double输出是使用"%f"的,并非所有编译器都实现了"%lf"的输出(比如POJ的G++就没有)。
4、在实在没有办法的情况下可以使用long double,但标准只规定了其精度一定不小于double,有可能等于double请注意。
5、double的精度有限,并不是精确的存储数字,而且它是二进制存储,如下图,0.1 * 10不等于1,因为0.1在计算机中不是我们认为的1/10,下图有0.1在double下的值,可以看出并不完全等于0.1。
6、为了解决上面不能直接比较的问题,我们可以设置一个精度EPS,来辅助我们检验两个数是否非常接近。EPS的设置要看题目具体情况,一般情况下可以设成1e-8。
定义函数:
- inline int sgn(double x) {
- if(fabs(x) < EPS) return 0;
- return x > 0 ? 1 : -1;
- }
用上述函数来判断一个数是否大于小于或等于0。
x = 0 写成 sgn(x) == 0
x < 0 写成 sgn(x) < 0
x > 0 写成 sgn(x) > 0
x > y 写成 sgn(x - y) > 0
x == y 写成 sgn(x - y) == 0
x >= y 写成 sgn(x - y) >= 0
以此类推。
7、上述函数的一种常数优化的写法:
- inline int sgn(double x) {
- return (x > EPS) - (x < -EPS);
- }
二、进阶篇(陷阱篇)
1、在竞赛中,可能存在给一个double多次计算后,非常接近0的情况,但是,它可能是-0.000000000000000001(一下子举不出实际的例子……),这时输出会变成-0.00,在一部分精确比较的题目上可能会出错,解决方案为输出的时候加上一个EPS(当然不能排除出题人自己煞笔的情况……),即printf("%f", ans + EPS)。
2、如果一个double,要把一个数组里的浮点数累加起来(即 double sum = accumlate(arr.begin(), arr.end(), 0)),如果数组里的数相差可能会比较大,应该从小到大累加。否则可能会发生加了一个很大的浮点数之后,再加一个很小的浮点数,因为精度的原因,跟没加一样(比如一个极端的例子,1e100 + 1e-100还是等于1e100)。因为比较小的数多了,还是会影响到答案的,并不是可以简简单单被忽略的。
3、在计算一个数减去一组数的时候(即double sum = x - accumlate(arr.begin(), arr.end(), 0)),应该先把数组里的数全加起来,再用那个数来减。否则跟上面一样,可能会出现减去了一个很小的数,跟没减一样。
4、二分的时候,EPS设置不当,可能会出现奇怪的问题(特别是有多次二分而对着两次二分要求的精度不一样的时候),这时可以采取另一种写法:
- double binary_search(double l, double r) {
- for(int i = 0; i < 100; ++i) {
- double mid = (l + r) / 2;
- if(check(mid)) l = mid;
- else r = mid;
- }
- return l;
- }
循环次数可按需设置,一般100都够,对时间要求高可以设小一点。
5、在连乘的时候,浮点数可能会丢比较多的精度,此时可以利用公式x1 * x2 * …… * xn = exp(ln(x1 * x2 * …… * xn)) = exp(ln(x1) + ln(x2) + ……ln(xn)),取他们的对数相加,再求次幂。
比如在计算阶乘的时候,可以:
- double Factorial(int n) {
- double res = 0;
- for(int i = 1; i <= n; ++i)
- res += log(i);
- return exp(res);
- }
当然有必要的时候(其实是大多时候)我们可以先不exp()先返回,作完后续运算再exp()
6、待补充
IO/ACM中来自浮点数的陷阱(收集向)的更多相关文章
- ACM中的浮点数精度处理
在ACM中,精度问题非常常见.其中计算几何头疼的地方一般在于代码量大和精度问题,代码量问题只要平时注意积累模板一般就不成问题了.精度问题则不好说,有时候一个精度问题就可能成为一道题的瓶颈,让你debu ...
- Java在ACM中的应用
Java在ACM中的应用 —. 在java中的基本头文件(java中叫包) import java.io.*; import java.util.*; //输入Scanner import java. ...
- ACM中Java的应用
先说一下Java对于ACM的一些优点吧: (1) 对于熟悉C/C++的程序员来说Java 并不难学,两周时间基本可以搞定一般的编程,再用些时间了解一下Java库就行了.Java的语法和C++非常类似, ...
- [原创]浅谈JAVA在ACM中的应用
由于java里面有一些东西比c/c++方便(尤其是大数据高精度问题,备受广大ACMer欢迎),所以就可以灵活运用这三种来实现编程,下面是我自己在各种大牛那里总结了一些,同时加上自己平时遇到的一些jav ...
- Java中的BigInteger在ACM中的应用
Java中的BigInteger在ACM中的应用 在ACM中的做题时,常常会遇见一些大数的问题.这是当我们用C或是C++时就会认为比較麻烦.就想有没有现有的现有的能够直接调用的BigInter,那样就 ...
- ACM中java的使用
ACM中java的使用 转载自http://www.cnblogs.com/XBWer/archive/2012/06/24/2560532.html 这里指的java速成,只限于java语法,包括输 ...
- ACM 中JAVA的应用
原文地址:http://www.cppblog.com/vontroy/archive/2010/05/24/116233.html 先说一下Java对于ACM的一些优点吧: (1) 对于熟悉C/C+ ...
- ACM中java的使用 (转)
ACM中java的使用 这里指的java速成,只限于java语法,包括输入输出,运算处理,字符串和高精度的处理,进制之间的转换等,能解决OJ上的一些高精度题目. 1. 输入: 格式为:Scanner ...
- [ACM训练] ACM中巧用文件的输入输出来改写acm程序的输入输出 + ACM中八大输入输出格式
ACM中巧用文件的输入输出来改写acm程序的输入输出 经常有见大神们使用文件来代替ACM程序中的IO,尤其是当程序IO比较复杂时,可以使自己能够更专注于代码的测试,而不是怎样敲输入. C/C++代码中 ...
随机推荐
- Hibernate 一级缓存的陷阱
最近公司的应用经常报OOM,一开始我以为是公司业务数据太多,导致内存不够,所以只是简单的把容器的内存加大.撑了几天后这个错仍然被报出来.后来我仔 细分析过项目代码后,没有发现有任何引起内存泄漏的地方. ...
- 配置hooks使svn提交后自动同步客户端代码(客户端与服务端在同一台机器上)
1.配置svn的hooks 2.实例演示 1.配置svn的hooks 1.1)配置情况 承接上篇svn搭建的文章,今次继续使用上篇文章的配置 上篇文章的地址:linux下搭建svn代码库 svn仓库所 ...
- MongoDB使用操作
一.mongodb常用命令 http://www.cnblogs.com/cxd4321/archive/2011/06/24/2089051.html 二.MongoDB基本使用 http://ww ...
- IE6及以上版本fixed问题解决方案,页面右下角固定页面,可以最大化、最小化、正规显示
在窗口固定位置显示内容使用fixed,但是 IE 6 不支持,后来我搜了很多方法,都没有作用,后来类比着一个网站的代码,使用absolute .z-index解决了问题. 页面div结构: <d ...
- JQuery的动画及其幻灯片效果
1.显示和隐藏hide()和show() 对于动画来说,显示和隐藏是最基本的效果之一,简单介绍jQuery的显示和隐藏. <script type="text/javascript&q ...
- android中的ActionBar和ToolBar
一.ToolBar 1.概述 Google在2015的IO大会上发布了系列的Material Design风格的控件.其中ToolBar是替代ActionBar的控件.由于ActionBar在各个安卓 ...
- 三种线程不安全现象描述(escaped state以及hidden mutable state)
hidden mutable state和escaped state是两种线程不安全问题:两者原因不同,前者主要是由于类成员变量中含有其他对象的引用,而这个引用是immutable的:后者是成员方法的 ...
- Logistic Regression Vs Decision Trees Vs SVM: Part I
Classification is one of the major problems that we solve while working on standard business problem ...
- thinkphp 的save()不能更新数据解决办法
用save()方法始终更新不了数据,又不显示明确的错误信息,找了好久才在手册里看到一句至关重要的话: 为了保证数据库的安全,避免出错更新整个数据表,如果没有任何更新条件,数据对象本身也不包含主键字段的 ...
- js console 一些拓展技巧
console.time 方法 / console.timeEnd() 方法 统计一段代码的执行时间, 形参必须一致 console.time("string"); for(var ...