toc] ## 本篇要点 - 简单描述浮点数十进制转二进制精度丢失的原因。 - 介绍几种创建BigDecimal方式的区别。 - 整理了高精度计算的工具类。 - 学习了阿里巴巴Java开发手册关于BigDecimal比较相等的规定。 ## 经典问题:浮点数精度丢失 精度丢失的问题是在其他计算机语言中也都会出现,float和double类型的数据在执行二进制浮点运算的时候,并没有提供完全精确的结果。产生误差不在于数的大小,而是因为数的精度。 关于浮点数存储精度丢失的问题,话题过于庞大,感兴趣的同学可以自行搜索一下:[【解惑】剖析float型的内存存储和精度丢失问题](
) 这里简单讨论一下十进制数转二进制为什么会出现精度丢失的现象,十进制数分为整数部分和小数部分,我们分开来看看就知道原因为何: ### 十进制整数如何转化为二进制整数? 将被除数每次都除以2,只要除到商为0就可以停止这个过程。 ```java 5 / 2 = 2 余 1 2 / 2 = 1 余 0 1 / 2 = 0 余 1 // 结果为 101 ``` 这个算法永远都不会无限循环,整数永远都可以使用二进制数精确表示,但小数呢? ### 十进制小数如何转化为二进制数? 每次将小数部分乘2,取出整数部分,如果小数部分为0,就可以停止这个过程。 ```java 0.1 * 2 = 0.2 取整数部分0 0.2 * 2 = 0.4 取整数部分0 0.4 * 2 = 0.8 取整数部分0 0.8 * 2 = 1.6 取整数部分1 0.6 * 2 = 1.2 取整数部分1 0.2 * 2 = 0.4 取整数部分0 //... 我想写到这就不必再写了,你应该也已经发现,上面的过程已经开始循环,小数部分永远不能为0 ``` 这个算法有一定概率会存在无限循环,即无法用有限长度的二进制数表示十进制的小数,这就是精度丢失问题产生的原因。 ## 如何用BigDecimal解决double精度问题? 我们已经明白为什么精度会存在丢失现象,那么我们就应该知道,当某个业务场景对double数据的精度要求非常高时,就必须采取某种手段来处理这个问题,这也是BigDecimal为什么会被广泛应用于金额支付场景中的原因啦。 > BigDecimal类位于`j
