A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© cat73 黑马帝   /  2016-1-9 21:38  /  1671 人查看  /  13 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 cat73 于 2016-1-9 21:48 编辑

有如下 Java 代码,其输出结果已经在后面以注释的形式给出↓
  1. double a = 0.2d;
  2. double b = 0.4d;
  3. double n = a + b;
  4. double n2 = 0.6d;

  5. System.out.println(a); //  0.2
  6. System.out.println(b); //  0.4
  7. System.out.println(n); //  0.6000000000000001
  8. System.out.println(n2); // 0.6
复制代码

在 JavaScript、Python3 中可以得出相同的结果。
那么问题来了,为什么会出现这样的结果呢?

=============================

现在再打开你电脑上自带的计算器试试,0.2 + 0.4 = 0.6!
为何计算器可以得出正确的结果呢?
我们又要如何才能在编程中得到正确的结果呢?

13 个回复

正序浏览
本帖最后由 好好搬砖 于 2016-1-11 16:24 编辑

###14.15_常见对象(BigDecimal类的概述和方法使用)
* A:BigDecimal的概述
        * 由于在运算的时候,float类型和double很容易丢失精度,演示案例。
        * 所以,为了能精确的表示、计算浮点数,Java提供了BigDecimal
        * 不可变的、任意精度的有符号十进制数。
* B:构造方法
        * public BigDecimal(String val)
* C:成员方法
        * public BigDecimal add(BigDecimal augend)
        * public BigDecimal subtract(BigDecimal subtrahend)
        * public BigDecimal multiply(BigDecimal multiplicand)
        * public BigDecimal divide(BigDecimal divisor)
* D:案例演示
        * BigDecimal类的构造方法和成员方法使用
-------------------------------为何会出现不精准的问题,参考知乎的回答---------------------------------
https://www.zhihu.com/question/28551135

M{ (132.27 KB, 下载次数: 12)

M{
回复 使用道具 举报
cat73 发表于 2016-1-10 22:32
那么现在就解决了其中一个问题:如何避免计算时出现不精准的问题。
但是还是没有搞清楚,为何会出现不精 ...

为何会出现不精准的问题?参考知乎的回答。
https://www.zhihu.com/question/28551135
回复 使用道具 举报
我是坏人, 发表于 2016-1-10 22:36
直接运算底层用的是2进制补码运算的,  

BigDecimal完美解决

确实我也不太清楚到底是为什么,不过建议你想知道的话去看看IEEE754,这个是浮点数储存的标准。
应该是与浮点数在内存中储存的方式有关系,我是没看太懂
回复 使用道具 举报
感觉都好厉害啊  
回复 使用道具 举报
就想你用double表示10,他就是10.0,但你用double表示个10/3试试,3.33333333333333333333....

点评

看问题吖?10 / 3或许是不能精准的被表示,但是 0.2、0.4、0.6 都可以精准的用 double 表示出来,在这种情况下结果为何依旧是错的,这才是我的问题。  发表于 2016-1-12 14:19
回复 使用道具 举报
BigDecimal就是解决的方法,至于原因:类似于10进制中标识1/3一样,你只能得到0.333333333...却永远无法精确,二进制中也有一些无限循环的小数无法精确表示,所以就造成了你代码中的结果

点评

根据测试代码,我们可以看出,0.2、0.4、0.6 都可以精准的用 double 表示出来,那么为何结果却错了。  发表于 2016-1-11 15:05
回复 使用道具 举报
直接运算底层用的是2进制补码运算的,  

BigDecimal完美解决

点评

所以你还是没说明白,计算过程中到底发生了什么,才导致了不精准的问题。  发表于 2016-1-10 22:46
回复 使用道具 举报
cat73 黑马帝 2016-1-10 22:32:31
报纸
好好搬砖 发表于 2016-1-10 16:00
###14.15_常见对象(BigDecimal类的概述和方法使用)
* A:BigDecimal的概述
        * 由于在运算的时候,float类型 ...

那么现在就解决了其中一个问题:如何避免计算时出现不精准的问题。
但是还是没有搞清楚,为何会出现不精准的问题。
我们已经知道 0.2、0.4、0.6 都可以精准的用 double 表示出来。
也就是说 0.2 + 0.4 的结果 0.6 是可以被 double 表示出来的。
那为何实际计算的结果为 0.6000000000000001 呢?
回复 使用道具 举报
BigDecimal 对象就是为你这个问题量身定做的啊骚年!!!
回复 使用道具 举报 1 0
变成字符串对象再操作就Ok.至于为啥,我也不晓得...
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马