Java中的BigDecimal原理详解
作者:feiyingHiei
BigDecimal原理
一、浮点数的精度问题
对于日常开发过程中出现小数的问题,通常都是使用float或者double类型来处理,在java中float占用四个字节, double类型占用8个字节,简单的从double类型来说,计算机中存储的格式为
位数 | 功能 |
63 | 符号位 |
62 - 52 | 指数位 |
51-0 | 尾数 |
一个浮点数的数值 d=±1.f×2E−127
比如一个浮点数1.5,转换成二进制就是1.1,套用上述的公式 f=1, fraction=127,转换成二进制数为0 00111111111 1000000000000000000000000000000000000000000000000
通过代码的方式来验证一下
System.out.println(Long.toBinaryString(Double.doubleToLongBits(1.5d)));
输出的结果为
11111111111000000000000000000000000000000000000000000000000000
和我们的计算结果相同。看到这里,很容易就发现,浮点数是依赖2的负数次幂求和来表示十进制数的,那么就必然存在着精度的问题,比如,十进制中的0,通过上述公式计算是永远无法获得的。在表示0的时候, f = 0 f=0 f=0, e x p o n e n t = 0 exponent=0 exponent=0, 那么 d = 1.0 × 2 − 127 d=1.0 \times 2^{-127} d=1.0×2−127, 所以会发现使用这种方式表示浮点数是有精度问题的,在精度要求不高的场景下,我们可以使用原生的浮点数来处理,但是当我们在对精度有很高要求的场景时,使用dobule就无法满足我们的需求了。
BigDecimal
在Java中,jdk为我们提供了bigDecimal,bigDecimal解决了浮点数的精度问题,下面就看一下BigDecimal是如何解决这个问题的,废话不多说,直接上源码
public class BigDecimal extends Number implements Comparable<BigDecimal> { private final BigInteger intVal; private final int scale; private transient int precision; private transient String stringCache; }
主要的存储方式是通过intVal和scale来表示,d=intVal×10−scale
所以当需要表示1.1的时候,只需要 intVal=11 然后 scale=1即可。这种情况下就不会丢失精度了。
到此这篇关于Java中的BigDecimal原理详解的文章就介绍到这了,更多相关BigDecimal原理内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!