使用BigDecimal替代Double完成精确计算

double和float为什么不能精确计算

在计算机中,为了提高运算效率,数值型使用二进制进行运算,但是对于double和float这类小数来说,不是所有的十进制数都能转化为有限位二进制数的,也就是十进制整数在转化成二进制数时会有精度问题,常会使用近似值替代原小数完成运算,这就导致使用double和floa进行计算可能出现误差。

相关知识:

小数的二进制表示和计算

BigDecimal的基础使用

构造器

  1. BigDecimal(int)

    创建一个具有参数所指定整数值的对象

  2. BigDecimal(double)

    创建一个具有参数所指定双精度值的对象

  3. BigDecimal(long)

    创建一个具有参数所指定长整数值的对象

  4. BigDecimal(String)

    创建一个具有参数所指定以字符串表示的数值的对象

注意:对于小数,推荐使用BigDecimal(double)而不推荐使用BigDecimal(String)

加减乘除

  1. BigDecimal add(BigDecimal):加法。将BigDecimal对象中的值加上入参,然后返回

  2. BigDecimal subtract(BigDecimal):减法。将BigDecimal对象中的值减去入参,然后返回

  3. BigDecimal multiply(BigDecimal):乘法。将BigDecimal对象中的值乘上入参,然后返回

  4. BigDecimal add(BigDecimal):除法。将BigDecimal对象中的值除以入参,然后返回商

精度的使用

BigDecimal setScale(int scale, RoundingMode roundingMode) :设置精度。对BigDecimal数据小数点后的位数进行进位、舍位、截断等操作。scale是精度值,roundingMode是舍入规则如四舍五入等。

对于加减乘除方法,也可以使用相应的重载方法如BigDecimal add(BigDecimal,)

舍入规则:

  • ROUND_CEILING:舍向正无穷

  • ROUND_UP:直接加1

  • ROUND_DOWN:直接舍弃掉后面的数

  • ROUND_FLOOR:舍向负无穷

  • ROUND_HALF_DOWN:四舍五入,大于5向前进1

  • ROUND_HALF_EVEN:接近负无穷大的舍入模式

  • DOUND_HALF_UP:四舍五入,大于等于5向前进1

大小比较

  • BigDecimal equals(BigDecimal):判断是否相等,值和精度相等时返回true,否则返回false

  • BigDecimal compareTo(BigDecimal):比较大小。大于返回1,小于返回-1,等于返回0

BigDecimal需要注意的坑

正确使用构造器

对于小数,推荐使用BigDecimal(double)而不推荐使用BigDecimal(String)。

参数类型为double的构造方法的结果有一定的不可预知性。有人可能认为在Java中写入newBigDecimal(0.1)所创建的BigDecimal正好等于 0.1(非标度值 1,其标度为 1),但是它实际上等于0.1000000000000000055511151231257827021181583404541015625。这是因为0.1无法准确地表示为 double(

或者说对于该情况,不能表示为任何有限长度的二进制小数)。这样,传入到构造方法的值不会正好等于 0.1(虽然表面上等于该值)。String 构造方法是完全可预知的:写入 newBigDecimal(“0.1”) 将创建一个 BigDecimal,它正好等于预期的 0.1。因此,比较而言, 通常建议优先使用String构造方法。

当double必须用作BigDecimal的源时,请注意,此构造方法提供了一个准确转换;它不提供与以下操作相同的结果:先使用Double.toString(double)方法,然后使用BigDecimal(String)构造方法,将double转换为String。要获取该结果,请使用static valueOf(double)方法。

使用compareTo()比较

BigDecimal的equals方法,当且仅当指定的Object是一个BigDecimal,其值和比例都等于该BigDecimal时才返回true。

BigDecimal的compareTo方法,只需要值相等即返回true。

在开发中使用BigDecimal比较是否相等时,应当注意使用equals还是compareTo。

divide使用精度控制避免除不尽

在进行除法运算的时候,结果不能整除,有余数,这个时候会报java.lang.ArithmeticException,在实际使用中,为了避免这个错误,在进行除法运算的时候,使用divede(BigDeciaml divisor,int scale,int roundingMode),scale是要保留的小数位数,roundingMode是保留规则。

在开发中,凡是使用除法运算时,都应传入scale和roundingMode两个参数

BigDecimal“不可变”应该返回新对象

在使用BigDecimal的方法,如setScale、add等方法时,应该返回一个新的BigDecimal使用,原BigDecimal是不可变的。

你可能感兴趣的:(Java基础,BigDecimal,Double,小数运算)