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. 左偏树(Leftist Heap/Tree)简介及代码

    左偏树是一种常用的优先队列(堆)结构.与二叉堆相比,左偏树可以高效的实现两个堆的合并操作. 左偏树实现方便,编程复杂度低,而且有着不俗的效率表现. 它的一个常见应用就是与并查集结合使用.利用并查集确定 ...

  2. window FILES——windows文件管理相关实例

    C语言下有一套文件管理方案.C++语言下也有一套自己的文件管理方案.windows系统当然也有自己的一套文件管理方案啦.对于普通char类型为基础的字符使用哪种方案的解决办法都是一样的,但是对于宽字符 ...

  3. 网页登陆校验码C#版代码

    [DefaultProperty("Text")] [ToolboxData("<{0}:ValidateCode runat=server></{0} ...

  4. css3多行省略号

    -webkit-line-clamp 概述: -webkit-line-clamp 是一个 不规范的属性(unsupported WebKit property),它没有出现在 CSS 规范草案中. ...

  5. 2016022607 - redis配置文件

    在Redis有配置文件(redis.conf)可在Redis的根目录下找到.可以通过Redis的CONFIG命令设置所有Redis的配置. Redis的CONFIG命令的基本语法如下所示: redis ...

  6. 利用java实现一个简单的远程监控程序

    一般的远程监控软件都是用c或者c++等语言开发的,而使用java如何来实现相同的功能呢. 首先我们先介绍一下一个简单的远程监控程序的实现原理. 功能一,远程屏幕监视 (1) 必须要有监控端与被监控端, ...

  7. ASP.NET MVC轻教程 Step By Step 6——改进表单

    上一节我们使用原始的HTML表单来完成留言功能,但是ASP.NET MVC提供了丰富的HTML辅助方法来帮助我们构建更简洁优雅的表单. Step 1. 修改Form标签 首先,我们可以使用Html.B ...

  8. JDK下sun.net.www.protocol.http.HttpURLConnection类-----Http客户端实现类的实现分析

    HttpClient类是进行TCP连接的实现类, package sun.net.www.http; import java.io.*; import java.net.*; import java. ...

  9. ibatis错误

    java.lang.IllegalArgumentException: Mapped Statement collection already contains value for com.regin ...

  10. 各大Oj平台介绍[转]

    1.题库与网站资源题库-在线提交系统(Online Judge)简介   下面是几个比较大的在线提交系统(OnlineJudge)里面有大量历年的竞赛题目,注册一个ID,然后用自己熟悉的语言(一般有P ...