http://blog.csdn.net/androiddevelop/article/details/8478879

一  问题描述

float和double类型不能用于精确计算,其主要目的是为了科学计算和工程计算,它们执行二进制浮点原酸,目的是为了广泛的数值范围上提供较为精确的快速近似计算而精心设计的。但是如果设计钱币之类的计算需要很精确,所以这种情况不能使用float和double,因为要让其精确表示0.1 或者 10的任何负数次方值是不可能的。

二 眼见为实,举例证明:

  1. // float与double 无法精确表示0.1 或者 10的负次方
  2. System.out.println( 0.15 - 0.05 ); // 0.09999999999999999
  3. System.out.println( 2.08f - 3.7f );// -1.6200001

三 举一个现实中会遇到的情况:

一个实际的例子,口袋里面有10元钱,买0.9元的商品十个 , 收银员需要找零1元。计算如下:

  1. 10 - 0.9 * 10 = 1

代码实现:

  1. float myMoney = 10.00f;
  2. float price = 0.9f;
  3. for (int i = 0; i < 10; i++) {
  4. myMoney -= price;
  5. }
  6. System.out.println( myMoney ); // 1.0000002

结果竟然输出的是1.0000002而非1,可能很多人会认为这也无所谓啊,毕竟仅偏差了0.0000002,但问题是如果前提是进行了1亿笔交易呢?难道你愿意仅仅因为使用了计算机计算这些数据,而损失一部分钱吗?

四 解决办法

1. 使用int 和 long类型,如果小数点以后的值可以忽略不计可以只用这两种类型

2. 对计算结果进行四舍五入

3. 使用BigDecimal类型进行浮点运算

先来看一段代码

  1. int intValue = 10;
  2. float floatValue = 0.99999f;
  3. int count1 = (int) (intValue + floatValue);
  4. System.out.println("10 + 0.99999 = " +  count1); // output 10
  5. int count2 = (int) (intValue - floatValue);
  6. System.out.println("10 - 0.99999 = " +  count2); // output 9

原本按我个人的理解 10 + 0.99999 = 10.99999 然后转为int类型会进行四舍五入 值为11,而实际结果为10

更深入的分析可以查看



如何解决float和double误差问题呢?可以使用Java中提供的java.math.BigDecimal,不过此类型是不可变的,每次计算都必须新创建一个对象,不适合大量计算

再来看一个舍入误差会出现的问题

  1. // 10.1 + 0.99*10 = 20
  2. float f1 = 10.1f;
  3. float f2 = 0.99f;
  4. for (int i = 0; i < 10; i++) {
  5. f1 += f2;
  6. }
  7. System.out.println(f1); // 19.999998

解决办法,使用BigDecimal

  1. BigDecimal count = new BigDecimal("10.1");
  2. for (int i = 0; i < 10; i++) {
  3. count = count.add(new BigDecimal("1"));
  4. }
  5. System.out.println(count.intValue()); // 20

参考资料:

1. Java 理论与实践: 您的小数点到哪里去了?

2. 《Effective Java》 第2版 第48条 如果需要精确的答案,请避免使用float和double

不要在精确计算中使用float和double类型的更多相关文章

  1. Java中的float、double计算精度问题

    java中的float.double计算存在精度问题,这不仅仅在java会出现,在其他语言中也会存在,其原因是出在IEEE 754标准上. 而java对此提供了一个用于浮点型计算的类——BigDeci ...

  2. C#中对于float,double,decimal的误解

    原文:C#中对于float,double,decimal的误解 一直很奇怪C#的预定义数据类型中为什么加了一个decimal,有float和double不就够了吗?今天来挖一挖. 浮点型 如果我们在代 ...

  3. Effective Java 第三版——60. 需要精确的结果时避免使用float和double类型

    Tips 书中的源代码地址:https://github.com/jbloch/effective-java-3e-source-code 注意,书中的有些代码里方法是基于Java 9 API中的,所 ...

  4. C#中对于float,double,decimal的误解(转载)

    浮点型 Name CTS Type Description Significant Figures Range (approximate) float System.Single 32-bit sin ...

  5. java中int,float,long,double取值范围,内存泄露

    java中int,float,long,double取值范围是多少? 写道 public class TestOutOfBound { public static void main(String[] ...

  6. MySQL中的float和decimal类型有什么区别

    decimal 类型可以精确地表示非常大或非常精确的小数.大至 1028(正或负)以及有效位数多达 28 位的数字可以作为 decimal类型存储而不失其精确性.该类型对于必须避免舍入错误的应用程序( ...

  7. 关于SQL中数据类型(float和real)和 .NET Framework 中数据类型(float和double)的问题

    今天同学写程序遇到一个问题,MSSQL里的数据是 float 类型,在 .NET Framework 中用的时候也转换成 float 类型,结果报错,类型转换异常,明明是相同的类型,为什么会异常 在w ...

  8. hive 中的float和double

    表employees中字段 taxes(税率)用类型float存储 hive> select name, salary, taxes from employees where taxes  &g ...

  9. C语言中关于float和double的输入输出格式

    1.对于double类型,输入格式为scanf("%lf %lf", &foo, &bar); 对于float类型,输入格式为scanf("%f %f, ...

随机推荐

  1. java设计模式——接口模式

    java将接口的概念提升为独立的结构,体现了接口与实现分离.java接口允许多个类提供相同的功能,也允许一个同时实现多个接口.java的接口与抽象类十分相似.java与抽象类中的区别: 1.一个类可以 ...

  2. Git 基本使用配置

    // 1.配置用户名邮箱:用于记录你个人的用户名称和电子邮件地址,用户名可随意修改,git 用于记录是谁提交了更新,以及更新人的联系方式: $ git config --global user.nam ...

  3. #Leet Code# Divide Two Integers

    描述:不使用 * / % 完成除法操作.O(n)复杂度会超时,需要O(lg(n))复杂度. 代码: class Solution: # @return an integer def dividePos ...

  4. In Place Upgrade of CentOS 6 to CentOS 7

    Note: This is not the most highly recommended method to move from CentOS 6 to CentOS 7 ... but it ca ...

  5. Linux运维需要掌握的技能 (转)

    本人是linux运维工程师,对这方面有点心得,现在我说说要掌握哪方面的工具吧说到工具,在行外可以说是技能,在行内我们一般称为工具,就是运维必须要掌握的工具.我就大概列出这几方面,这样入门就基本没问题了 ...

  6. 如何得到UBUNTU源代码

    http://www.pleaseguide.me/367/how-to-get-the-source-code-of-ubuntu 在按书作测试,有难点一一解决. Ubuntu's Source c ...

  7. 子元素div高度不确定时父div高度如何自适应

    粘自:http://www.jb51.net/css/110652.html 在最外层div加以下样式 height:100%; overflow:hidden; 其它方法: Div即父容器不根据内容 ...

  8. Initializing Spring root WebApplicationContext

    最近 我部署ssh项目的时候经常出现这样的问题,我的解决办法是 log4j:WARN No appenders could be found for logger (org.springframewo ...

  9. 关于sql语句in的使用注意规则( 转)

    select * from tuser where userno not in(select userno from filter_barcode) 上面这条语句子查询里,userno 并不存在fil ...

  10. Dynamics CRM 2011编程系列(60):JS编程之CRUD辅助类(JQuery版)

    今天给大家分享一个JQuery版的REST辅助类,在一年前我分享过一个只能在IE环境下运行的REST辅助类:<JS编程之实体CRUD辅助类 >.为什么要推出JQuery版的CRUD辅助类呢 ...