加减乘除运算
add():加法, subtract():减法:, multiply():乘法; divide():除法。
public class test {
public static void main(String[] args) {
BigDecimal num1 = new BigDecimal("100");
BigDecimal num2 = new BigDecimal("200");
System.out.println("num1 = " + num1 + ",num2 = " + num2);
// num1 + num2
BigDecimal add = num1.add(num2);
System.out.println("num1 + num2 = " + add);
// num2 - num1
BigDecimal subtract = num2.subtract(num1);
System.out.println("num2 - num1 = " + subtract);
// num1 * mun2
BigDecimal multiply = num1.multiply(num2);
System.out.println("num1 * num2 = " + multiply);
// num2 /num1
BigDecimal divide = num2.divide(num1);
System.out.println("num2 / num1 = " + divide);
}
}
除法运算要指定精度
bigdecimal在进行除法运算时一定要指定精度,否则会因为除不尽报错:
Exception in thread "main" java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
at java.math.BigDecimal.divide(BigDecimal.java:1690)
at com.fh.iasp.app.dingzhi_kenvueotc.TestMain.main(TestMain.java:11)
除法指定精度,最常用的就是四舍五入保留2位小数:
BigDecimal num1 = new BigDecimal("20");
BigDecimal num2 = new BigDecimal("3");
BigDecimal divide = num1.divide(num2,2,BigDecimal.ROUND_HALF_UP);
System.out.println(divide);
结果:6.67
指定精度方法
除了进行除法运算时在除法运算方法内部指定精度,我们还需要在进行其他运算或者单纯对Bigdecimal的数据进行精度指定,通过bigdecimal内部方法:.setScale() 实现
BigDecimal num1 = new BigDecimal("20");
BigDecimal num2 = new BigDecimal("3");
BigDecimal divide = num1.multiply(num2).setScale(2,BigDecimal.ROUND_HALF_UP);
System.out.println(divide);
精度舍入模式种类
// ROUND_HALF_UP 在保留精度前提下,四舍五入(五入)
// ROUND_HALF_DOWN 在保留精度前提下,四舍五入(五舍)
// ROUND_UP 在保留精度前提下,舍弃精度后面位数,同时加1,直接入
// ROUND_DOWN 在保留精度前提下,直接舍弃精度后面位数,直接舍
// ROUND_CEILING 接近正无穷大的舍入模式。如果 BigDecimal 为正,则舍入行为与 ROUND_UP 相同;如果为负,则舍入行为与 ROUND_DOWN 相同。
// ROUND_FLOOR 接近负无穷大的舍入模式。如果 BigDecimal 为正,则舍入行为与 ROUND_DOWN 相同;如果为负,则舍入行为与 ROUND_UP 相同。
// ROUND_HALF_EVEN 向最接近的数字舍入,如果与两个相邻数字的距离相等,则向相邻的偶数舍入。
// ROUND_UNNECESSARY 计算结果是精确的,不需要舍入模式。如果对获得精确结果的操作指定此舍入模式,则抛出ArithmeticException。
通常最常用的就是四舍五入:ROUND_HALF_UP
其他方法
取绝对值:abs()
转双精度:doubleValue()
转单精度:floatValue()
转长整型:longValue()
转短整型:intValue()
比较大小:
compareTo(BigDecimal val)
比较大小,返回int类型。0(相等) 1(大于) -1(小于)
转字符串:toString()
转字符串(推荐使用):toPlainString()
toPlainString()方法以字符串形式返回BigDecimal的数值,不带指数字段,即不会出现科学计数法形式。
两数比较取最大值:max(BigDecimal val)
求相反数:negate()
求相反数,正变负,负变正
求乘方:pow(int n)
求乘方,如BigDecimal.valueOf(2).pow(3)的值为8
使用bigdecimal常见问题
1、创建bigdecimal时精度丢失
在使用BigDecimal构造函数时,尽量传递字符串而非浮点类型;
如果无法满足第一条,则可采用BigDecimal#valueOf方法来构造初始化值。但是valueOf受double类型精度影响,当传入参数小数点后的位数超过double允许的16位精度还是可能会出现问题的。
如下源码所示,BigDecimal#valueOf 中是把浮点数转换成了字符串来构造的BigDecimal,因此避免了问题。
public static BigDecimal valueOf(double val) {
return new BigDecimal(Double.toString(val));
}
2、等值比较的坑
在BigDecimal 中使用equals可能会导致结果错误,因为不仅比较值的大小,还比较了值的精度。所以相比较值的大小,需要使用compareTo。
3、除法无限精度的坑
BigDecimal 并不代表无限精度,当在两个数除不尽的时候,就会报错。前面单独讲了。
4、三种字符串输出的坑
BigDecimal 转换成字符串时,有可能输出非你预期的结果。如下所示:
public static void main(String[] args){
BigDecimal bg = new BigDecimal("1E11");
System.out.println(bg.toString()); // 1E+11
System.out.println(bg.toPlainString()); // 100000000000
System.out.println(bg.toEngineeringString()); // 100E+9
}
结果:
1E+11
100000000000
100E+9
区别:
toPlainString() : 不使用任何指数。
toString() :有必要时使用科学计数法。
toEngineeringString():有必要时使用工程计数法。 工程记数法是一种工程计算中经常使用的记录数字的方法,与科学技术法类似,但要求10的幂必须是3的倍数
5、在进行运算时确保参数不为null
在使用BigDecimal类型进行计算时,进行加、减、乘、除、比较大小时,一定要保证参与计算的两个值不能为空,否则会抛出java.lang.NullPointerException异常。
6、除法时被除数不能为0
否则报错:
Exception in thread "main" java.lang.ArithmeticException: Division by zero