Java代码  
  1. double d = 29.0 * 0.01;
  2. System.out.println(d);
  3. System.out.println(d * 100);
  4. System.out.println((int) (d * 100));

输出:

Java代码  
  1. 0.29
  2. 28.999999999999996
  3. 28
Java代码  
  1. float f = (float) (29.45*0.01);
  2. System.out.println(f);
  3. System.out.println(f * 100);
  4. System.out.println((int) (f * 100));

输出:

Java代码  
  1. 0.2945
  2. 29.449999
  3. 29
Java代码  
  1. //需要使用String初始化对象
  2. BigDecimal x = new BigDecimal("500000000.00");
  3. BigDecimal y = new BigDecimal("0.6");
  4. BigDecimal z = x.multiply(y);
  5. System.out.println(">>>>>>>>>> "+z);
  6. >>>>>>>>>> 300000000.000
  7. BigDecimal x2 = new BigDecimal(500000001);
  8. BigDecimal y2 = new BigDecimal(0.6);
  9. BigDecimal z2 = x2.multiply(y2);
  10. >>>>>>>>>> 300000000.59999998889776973154397410326055251061916351318359375
  11. System.out.println(">>>>>>>>>> "+z2);
Java代码  
  1. BigDecimal equals
  2. * this method considers two BigDecimal objects
  3. * equal only if they are equal in value and scale
  4. * thus 2.0 is not equal to 2.00 when compared by this method.

照例,还是来一段Effective Java的内容。内容大家应该已经都熟悉,不过还是发现很多新人完全不清楚,所以拿来共享一下。
一、病例:

Java code
System.out.println(1.03-0.42); // 0.6100000000000001System.out.println(1.00-9*0.10); //0.09999999999999998

又比如,每个单价0.10元,0.20元,0.30元,0.40元……,每种比前一种多0.10元。每样买一个,1元钱能买几个,找零多少

Java code
publicstaticvoid main(String[] args) { double funds =1.00; int itemsBought =0; for (double price =.10; funds >= price ; price += .10) { funds -= price; itemsBought++; } System.out.println(itemsBought +" items bought."); System.out.println("Change: $"+ funds); }

如果运行这个程序,它会告诉你共可以买3样,找零$0.3999999999999999,显然这是错误答案。

二、原因:
float/double不能停供完全精确的计算结果。这个原理其实很简单,float/int都是32bit(也就是一共有2^32个精确值),而int的范围是-2^31 ~ 2^31-1,而Float的最大值是3.4028235e+38,远大于2^31 - 1。而且,int只负责个数有限的整数,而浮点却要用来表示个数无穷的小数,显然力不从心。

浮点精确值可以简单视作一个以0为中心的正态分布,绝对值越小(越接近0的地方),相邻两个精确值月密集。比如,最近的两个值可能只相差0.00000...几十个0...01,而最远的两个精确值,却差了2.028241E31。浮点的表示采用IEEE 754,大家可以参考一下。

另外浮点数特别不适合用于货币计算。因为浮点型不可能精确表示0.1或者任何10的负数次幂的值。同样,如果计算的数字极大,或者精度要求很高,也不应该用浮点进行计算。

三、解决方案
A java.math.BigDecimal
与浮点不同,它可以提供精度任意(当然在硬件限制范围内)的计算结果,但是,只能进行四则运算或者基于四则运算的其他简单运算。

Java code
publicstaticvoid main(String[] args) { BigDecimal funds =new BigDecimal("1.00"); int itemsBought=0; for (BigDecimal price =new BigDecimal(".10"); funds.compareTo(price) >=0; price =price.add(new BigDecimal(".10"))) { funds = funds.subtract(price); itemsBought++; } System.out.println(itemsBought +" items bought."); System.out.println("Change: $"+ funds); }

需要注意的是:
1 虽然提供了double型构造函数或方法,但是仍然应使用String以提高精度
2 BigDecimal与String,Integer等类似,为不可变对象(Immutable),计算结果需要重新赋值给变量,下面的代码,没有任何效果。

Java code
a.add(b);

3 对于有些可能影响精度的计算(比如除法除不尽)可能需要提供计算结果的精确度及取舍依据。当然@since 1.5,可以不再提供,但是如果无法得出精确值或者除不尽,仍会ArithmeticException

Java code
a.divide(b, 3, // 保留3位小数BigDecimal.ROUND_HALF_UP); // 四舍五入,see BigDecimal.ROUND_XXXX,

ROUND_HALF_UP 四舍五入最常见
ROUND_HALV_EVEN 奇进偶不进,末尾如果不是5,同四舍五入 0.129 --> 0.13,末尾如是5,参考前一位奇偶 0.125 --> 0.12 0.115 --> 0.12,在科学计算时较常见,特别是有舍入后累加的情况,好于四舍五入
ROUND_DOWN,去尾,货币计算让零较常见

B int/long
在有些情况下,float/double可以直接用int/long替代。包括有些情况下的数据库存储也类似。
只说一句话,大家应该可以理解。话说:
1米 = 10分米 = 100厘米 = 1000毫米
1元 = 10角 = 100分

货币等精确计算使用BigDecimal相关推荐

  1. Java除法不精确引入BigDecimal

    前言: 之前在项目里遇到一个问题:169/100=1.0 int nPtCount = 169; final int MAX_ROUTE_PT = 100; double lfDivide = 0;i ...

  2. bool转nsnumber ios_iOS开发之NSDecimalNumber的使用,货币计算/精确数值计算/保留位数等...

    iOS开发NSDecimalNumber的使用,货币计算/精确数值计算/保留位数等 NSDecimalNumber NSDecimalNumber,不可变NSNumber 的子类,提供了一个面向对象的 ...

  3. Java中使用BigDecimal进行浮点数精确计算 超大整数 浮点数等计算,没有数位限制...

    (注:前面写了一个超大整数相加的类,参见: 超大整数相加,超过了long的范围,你要怎么做!,后来有朋友评论说BigDecimal可以完全实现我的这这个功能,刚开始的时候,我还不服气,据我所知那里有这 ...

  4. Java 中商业运算必备的精确运算类:BigDecimal

    点击蓝色"程序猿DD"关注我 回复"资源"获取独家整理的学习资料! 作者 | 码农小胖哥 来源 | 公众号「码农小胖哥」 1. 前言 今天群里一个初级开发者问为 ...

  5. Java中使用BigDecimal进行浮点数精确计算 超大整数 浮点数等计算 没有数位限制

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! (注:前 ...

  6. bigdecimal 保留两位小数_不要以为你用了BigDecimal后,计算结果就一定精确了

    异常再现 大家应该都已经知道,涉及到金钱的计算应该使用BigDecimal,没有使用BigDecimal的已经被开除. 但是使用了BigDecimal后计算结果就一定是精确的吗?未必.看下面测试 Bi ...

  7. 你以为用了BigDecimal后,计算结果就一定精确了?

    BigDecimal,相信对于很多人来说都不陌生,很多人都知道他的用法,这是一种java.math包中提供的一种可以用来进行精确运算的类型. 很多人都知道,在进行金额表示.金额计算等场景,不能使用do ...

  8. 你以为用了 BigDecimal 后,计算结果就一定精确了?

    作者 | Hollis   责编 | 张文 来源 | 转载自 Hollis(ID:hollischuang) BigDecimal,相信对于很多人来说都不陌生,很多人都知道他的用法,这是一种 java ...

  9. java.math.BigDecimal记录

    2019独角兽企业重金招聘Python工程师标准>>> 1.引言 借用<Effactive Java>这本书中的话,float和double类型的主要设计目标是为了科学计 ...

最新文章

  1. XML学习笔记之XML的简介
  2. 【BLE】关于蓝牙的一些学习资料分享
  3. What to bring in UK?
  4. Some projects cannot be imported because they already exist in the workspace
  5. 计算机二级web题目(1)--web基础
  6. gdp笔记本 linux,linux中如何使用微软鼠标的第4、5键
  7. 大数据可视化html模板开源_8个可靠好用的开源数据可视化工具推荐
  8. 检测php加密方式,一种php加密方式
  9. CentOS 7 Linux实时内核下的epoll性能分析后续 | 火焰图分析
  10. 亚马逊数据线办理CE认证检测项目有哪些?如何办理?
  11. MFC入门到精通1-创建项目
  12. DOS系统和Windows系统的联系、对比和发展历程
  13. 学考计算机会考考点工作总结,高中生学业水平考试工作总结范文
  14. ISP Pipeline lens shading
  15. 了解掌握Java的循环语句、条件语句、分支语句(Java 从自学到就业 第3天)
  16. 电子书资源(建议珍藏,不断更新中)
  17. DNS域名解析TTL是什么?TTL值设置多少合适?
  18. micro python 语音识别_语音识别
  19. 2022-12-11 第 323 场周赛
  20. 环保制作废物利用计算机,生活中的“废物利用”大全!(环保、实用)

热门文章

  1. (重点)“Grid“网格布局
  2. mock测试 (mock-test 模仿测试)
  3. Python可视化:中国环保股上市公司市值Top20强
  4. 分组统计group by
  5. 商务部研究院信用所、启信宝联合发布《中国商务信用发展指数报告(2022)》
  6. 解决raw.githubusercontent.com地址DNS污染的方法参考
  7. 彻底卸载2345王牌输入法的方法
  8. 汽车改装之3G上网车载电脑篇
  9. 顺序查找(利用监视哨)的实现
  10. 计算机组成与体系结构 LRU 算法与 MRU 算法对比