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. 关于Apple设备私有的apple-touch-icon属性详解

    以前我们用过favicon在浏览器给网站进行身份标识,用法如下: <link href="http://image.feeliu.com/web/favicon.ico" r ...

  2. 【elasticsearch】(3)centos7 安装中文分词插件elasticsearch-analyzer-ik

    前言 elasticsearch(下面简称ES,安装ES点击这里)的自带standard分词只能把汉语分割成一个个字,而不能分词.分段,这就是我们需要分析器ik的地方了. 一.下载ik的相应版本 查看 ...

  3. CSS3圆角(border-radius)

    CSS3中的border-radius支持IE9+,chrome,firefox 2.3+,以及safari3.2+浏览器. border-radius可直接使用,无需加前缀(注意:firefox13 ...

  4. node 后台ajax文件(同时支持http、https)

    var http = require("http"), Url = require("url"), querystring = require('queryst ...

  5. smarty模板引擎原理解析

    //php 控制器文件 <?php//引入模板引擎文件include("20130304.php");$smarty =newTinySmarty();$qq_numbers ...

  6. AngularJS测试框架 karma备忘

    AngularJS测试框架karma安装 安装karma $ --save-dev 安装karma组件 $ npm install karma-jasmine karma-chrome-launche ...

  7. 从零开始学习MySQL2---MySQL的安装与配置(只有Windows)

    因为我电脑只装了Windows系统,故而,只整理了在Windows系统下的安装方式 截图比较麻烦,故而多引用百度经验. Windows平台下安装与配置MySQL 5.6 下载,网址:http://de ...

  8. Python 计算已经过去多少个周末

    def weekends_between(d1,d2): days_between = (d2-d1).days weekends, leftover = divmod(days_between,7) ...

  9. hdu3949 XOR xor高斯消元

    XOR Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submiss ...

  10. [HDOJ - 5208] Where is Bob 【DFS+按位贪心】

    题目链接:HDOJ - 5208 题目分析 使用按位贪心的思想,即从高位向低位枚举,尽量使这一位的答案为 1 . 我们使用 DFS ,每次就是对于  [l1, r1] [l2, r2] x  进行处理 ...