java之BigDecimal的加减乘除

在小数之间加减乘除的时候,由于二进制不能精确表示小数,从而导致精度丢失。在实际开发中,这种情况是很糟糕的。为了解决这一情况,我们可以利用BgiDecimal。但是这中间还有些问题需要注意的。

1、加减乘
首先,我们来看一个实例

BigDecimal num1 = new BigDecimal(3.0);
BigDecimal num2 = new BigDecimal(2.1);
System.out.println(num1.add(num2));
打印结果

并不是我们期望的结果,从jdk参考手册,我们可以找到原因
  1. The results of this constructor can be somewhat unpredictable. One might assume that writingnew BigDecimal(0.1) in Java creates aBigDecimal which is exactly equal to 0.1 (an unscaled value of 1, with a scale of 1), but it is actually equal to 0.1000000000000000055511151231257827021181583404541015625. This is because 0.1 cannot be represented exactly as adouble (or, for that matter, as a binary fraction of any finite length). Thus, the value that is being passedin to the constructor is not exactly equal to 0.1, appearances notwithstanding.
  2. The String constructor, on the other hand, is perfectly predictable: writingnew BigDecimal("0.1") creates aBigDecimal which is exactly equal to 0.1, as one would expect. Therefore, it is generally recommended that theString constructor be used in preference to this one.
  3. When a double must be used as a source for a BigDecimal, note that this constructor provides an exact conversion; it does not give the same result as converting thedouble to aString using the Double.toString(double) method and then using theBigDecimal(String) constructor. To get that result, use thestatic valueOf(double) method. 

我们再来看另外一个例子
BigDecimal num1 = BigDecimal.valueOf(3.0);
BigDecimal num2 = BigDecimal.valueOf(2.1);
System.out.println(num1.add(num2));

打印输出

这次是我们期望的结果。
所以,我创建BigDecimal对象的时候,最好通过静态方法valueOf(double)

当然,我们也可以通过另外一种方式。先将double值转为字符串,再通过Bigdecimal的构造函数创建对象
BigDecimal num1 = new BigDecimal(Double.toString(3.0));//或者3.0 + ""
BigDecimal num2 = new BigDecimal(Double.toString(2.1));//或者2.1 + ""
System.out.println("add->"+num1.add(num2));
System.out.println("subtract->"+num1.subtract(num2));
System.out.println("multiply->"+num1.multiply(num2));
打印输出

2.除
jdk提供了几种小数之间相除的方法。
BigDecimal num1 = new BigDecimal(3.0);
BigDecimal num2 = new BigDecimal(2.1);
System.out.println("divide->"+num1.divide(num2));
直接运行,奇怪的发现出现异常了

从异常信息可以知道,相除的结果不能够用二进制精确表示,所以需要使用另外一个方法

BigDecimal num1 = new BigDecimal(3.0);
BigDecimal num2 = new BigDecimal(2.1);
System.out.println("divide->"+ num1.divide(num2,3,RoundingMode.FLOOR));

第二个参数表示,当结果是无限小数时,保留几位有效数字
第三个参数表示,如何保留有效数字,例如四舍五入、向下取等

你可能感兴趣的:(java)