不要在精确计算中使用float和double类型
来源:互联网 发布:java自定义线程池实现 编辑:程序博客网 时间:2024/04/25 19:37
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
参考资料:
1. Java 理论与实践: 您的小数点到哪里去了?
2. 《Effective Java》 第2版 第48条 如果需要精确的答案,请避免使用float和double
0 0
- 不要在精确计算中使用float和double类型
- [读书笔记][Effective Java]不要在精确计算中使用float和double类型
- 在对于精确计算的要求下请不要使用float和double
- 精确计算时,不要使用float或double
- 精确计算java中float和double的精度
- 天天记录 - Java 精确计算避免使用float和double
- 做精确计算时应避免使用float和double
- 不要用float和double来进行精确的小数计算
- 精确运算避免使用float和double
- JAVA中实现double类型精确计算
- Java中浮点型数据Float和Double进行精确计算的问题
- Java 精确计算-double-float-String
- 需要精确答案,避免使用float和double
- Double、float类型精确到小数点后几位
- float、double、long double类型的变量在printf()和scanf()中的占位符使用区别
- Java中double float 类型的数据(小数)在作计算的时候要注意的
- java中double、float类型计算精度丢失问题
- Java在终端中实时计算时使用float还是double?
- win7 VS2010 Visual Assist X破解
- 黑马程序员 【】java学习之路——函数(学习日记)
- Smarty运行原理
- 怎么样可以获得跟多的积分
- ZOJ 1025
- 不要在精确计算中使用float和double类型
- eclipse maven maven-jetty git plugin setting
- ASCII码表
- Oracle插入数据速度最大化
- 时间的处理
- oracle知识总结和代码实例
- memcached的安装和使用
- UVA - 10892 LCM Cardinality (枚举因子)
- 珍惜今天才有明天