不要在精确计算中使用float和double类型
http://blog.csdn.net/androiddevelop/article/details/8478879
一 问题描述
float和double类型不能用于精确计算,其主要目的是为了科学计算和工程计算,它们执行二进制浮点原酸,目的是为了广泛的数值范围上提供较为精确的快速近似计算而精心设计的。但是如果设计钱币之类的计算需要很精确,所以这种情况不能使用float和double,因为要让其精确表示0.1 或者 10的任何负数次方值是不可能的。
二 眼见为实,举例证明:
- // float与double 无法精确表示0.1 或者 10的负次方
- System.out.println( 0.15 - 0.05 ); // 0.09999999999999999
- System.out.println( 2.08f - 3.7f );// -1.6200001
三 举一个现实中会遇到的情况:
一个实际的例子,口袋里面有10元钱,买0.9元的商品十个 , 收银员需要找零1元。计算如下:
- 10 - 0.9 * 10 = 1
代码实现:
- float myMoney = 10.00f;
- float price = 0.9f;
- for (int i = 0; i < 10; i++) {
- myMoney -= price;
- }
- System.out.println( myMoney ); // 1.0000002
结果竟然输出的是1.0000002而非1,可能很多人会认为这也无所谓啊,毕竟仅偏差了0.0000002,但问题是如果前提是进行了1亿笔交易呢?难道你愿意仅仅因为使用了计算机计算这些数据,而损失一部分钱吗?
四 解决办法
1. 使用int 和 long类型,如果小数点以后的值可以忽略不计可以只用这两种类型
2. 对计算结果进行四舍五入
3. 使用BigDecimal类型进行浮点运算
先来看一段代码
- int intValue = 10;
- float floatValue = 0.99999f;
- int count1 = (int) (intValue + floatValue);
- System.out.println("10 + 0.99999 = " + count1); // output 10
- int count2 = (int) (intValue - floatValue);
- System.out.println("10 - 0.99999 = " + count2); // output 9
原本按我个人的理解 10 + 0.99999 = 10.99999 然后转为int类型会进行四舍五入 值为11,而实际结果为10
更深入的分析可以查看
如何解决float和double误差问题呢?可以使用Java中提供的java.math.BigDecimal,不过此类型是不可变的,每次计算都必须新创建一个对象,不适合大量计算
再来看一个舍入误差会出现的问题
- // 10.1 + 0.99*10 = 20
- float f1 = 10.1f;
- float f2 = 0.99f;
- for (int i = 0; i < 10; i++) {
- f1 += f2;
- }
- System.out.println(f1); // 19.999998
解决办法,使用BigDecimal
- BigDecimal count = new BigDecimal("10.1");
- for (int i = 0; i < 10; i++) {
- count = count.add(new BigDecimal("1"));
- }
- System.out.println(count.intValue()); // 20
参考资料:
2. 《Effective Java》 第2版 第48条 如果需要精确的答案,请避免使用float和double
不要在精确计算中使用float和double类型的更多相关文章
- Java中的float、double计算精度问题
java中的float.double计算存在精度问题,这不仅仅在java会出现,在其他语言中也会存在,其原因是出在IEEE 754标准上. 而java对此提供了一个用于浮点型计算的类——BigDeci ...
- C#中对于float,double,decimal的误解
原文:C#中对于float,double,decimal的误解 一直很奇怪C#的预定义数据类型中为什么加了一个decimal,有float和double不就够了吗?今天来挖一挖. 浮点型 如果我们在代 ...
- Effective Java 第三版——60. 需要精确的结果时避免使用float和double类型
Tips 书中的源代码地址:https://github.com/jbloch/effective-java-3e-source-code 注意,书中的有些代码里方法是基于Java 9 API中的,所 ...
- C#中对于float,double,decimal的误解(转载)
浮点型 Name CTS Type Description Significant Figures Range (approximate) float System.Single 32-bit sin ...
- java中int,float,long,double取值范围,内存泄露
java中int,float,long,double取值范围是多少? 写道 public class TestOutOfBound { public static void main(String[] ...
- MySQL中的float和decimal类型有什么区别
decimal 类型可以精确地表示非常大或非常精确的小数.大至 1028(正或负)以及有效位数多达 28 位的数字可以作为 decimal类型存储而不失其精确性.该类型对于必须避免舍入错误的应用程序( ...
- 关于SQL中数据类型(float和real)和 .NET Framework 中数据类型(float和double)的问题
今天同学写程序遇到一个问题,MSSQL里的数据是 float 类型,在 .NET Framework 中用的时候也转换成 float 类型,结果报错,类型转换异常,明明是相同的类型,为什么会异常 在w ...
- hive 中的float和double
表employees中字段 taxes(税率)用类型float存储 hive> select name, salary, taxes from employees where taxes &g ...
- C语言中关于float和double的输入输出格式
1.对于double类型,输入格式为scanf("%lf %lf", &foo, &bar); 对于float类型,输入格式为scanf("%f %f, ...
随机推荐
- 找不好重现的bug的一个小技巧————守株待兔
最近碰到一个问题就是数据库中偶尔出现一条没有id的数据,可恨的是怎么也找不到重现这个问题的原因,只好换种方式来找了,那么就是我标题所说的守株待兔方法. 因为我发现出现bug的数据库里面的数据有个字段为 ...
- C++线程类的封装
简单的C++线程操作的封装,使用了智能指针管理对象的释放. 可运行对象基类 class SimpleRunable:public RefCountedBase { public: SimpleRuna ...
- ThinkPHP 中使用 PHPMailer 发送邮件 支持163和QQ邮箱等
[摘要]ThinkPHP是一个开源的PHP框架, 是为了简化企业级应用开发和敏捷WEB应用开发而诞生的.本文介绍ThinkPHP 中使用 PHPMailer 发送邮件. PHP是自带可以发送邮件的Ma ...
- 经典SQL练习题
题目地址:http://blog.csdn.net/qaz13177_58_/article/details/5575711 1. 查询Student表中的所有记录的Sname.Ssex和Class列 ...
- angular 跳转页面时传参
首先,你需要已经配置过你的rout,比如: $stateProvider .state('firstPage',{ url:'/Page/firstPage', templateUrl: 'Page/ ...
- Python学习 - 编写自己的ORM(2)
上一篇文章简单的实现了ORM(对象关系模型),这一篇文章主要实现简单的MySQL数据库操作. 想要操作数据库,首先要建立一个数据库连接.下面定义一个创建数据库连接的函数,得到一个连接叫做engine. ...
- JS中的call、apply、bind方法
JS中的call.apply.bind方法 一.call()和apply()方法 1.方法定义 call方法: 语法:call([thisObj[,arg1[, arg2[, [,.argN]]] ...
- 解决VS2015无法调试dotnet core项目
dotnet core 1.0正式版和VS2015 update3安装后一直无法在VS中正常调试. 错误提示:The debugger's worker process (msvsmon.exe) u ...
- iOS 细节 问题
1.当一个空指针(nil pointer)调用了一个方法会发生什么? 安然无恙 —— 这是oc自带的消息机制,nil也能发送消息,而不会报错 2.为什么retainCount绝对不能用在发布的代码中? ...
- div+css知识点(2)
文字溢出 显示省略号的 关键的三句代码text-overflow:ellipsis; -o-text-overflow:ellipsis; overflow:hidden;文字缩进的代码是什么text ...