bigdecimal运算和注意事项

加减乘除运算

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值