double存储小数的问题
众所周知,计算机存储整数使用的是二进制,但是存储小数时,并不是所有小数都能转成二进制,如0.1就不能直接用二进制表示,他的二进制是0.000110011001100… 这是一个无限循环小数。所以,计算机是没办法用二进制精确的表示0.1的;
人们想出了一种采用一定的精度,使用近似值表示一个小数的办法。这就是IEEE 754, IEEE754中,一个浮点数由符号位、尾数和阶码组成。符号位用于表示正数或负数,尾数是有效数字的部分,而阶码用于表示指数;
然而,计算机在存储浮点数时,指数和尾数能占用的bit位是固定的,十进制小数在转二进制小数时乘2取整,直到不存在小数为止,如果在运算时超过尾数限制的bit位长度,就会被截断,所以就导致小数精度发生损失;
BigDecimal底层原理
十进制整数在转化为二进制数时不会有精度问题,所以将十进制小数扩大N被让它在整数维度上进行计算(BigInteger类型),并记录小数点位置即可;
使用BigDecimal注意事项
- 不要使用BigDecimal(double),存在精度损失风险,因为实际存储的值是double数值的二进制表示,可能会有精度损失;
- 使用除法时,要指明roundingMode,否则遇到无限循环小数时,会报错; 3.BigDecimal等值比较时,使用CompareTo(),而不是equals(),因为equals会比较精度,而compareTo会忽略精度,那些无实际意义的0会自动忽略,比如2.0和2.00,compareTo返回是相等的,equals则不会。