BigDecimal 基本使用和常用方法

在商业计算中,为了确保数字精度,通常使用BigDecimal替代浮点数进行运算。本文介绍了BigDecimal的初始化、通过compareTo方法比较大小、设置精度及舍入模式、基本的加减乘除操作以及解决除法异常的方法。重点关注了BigDecimal的不可变性和精确计算特性,以及如何避免ArithmeticException。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景  

   涉及到比较大的数字之间的计算,使用float、double这样的浮点数就不那么准确了。因为不论是float 还是double都是浮点数,而计算机是二进制的,浮点数会失去一定的精确度。所以在商业计算中基本要用java.math.BigDecimal

一、初始化使用

    public static void main(String[] args) {
        // 可以使用
        BigDecimal bigDecimal1 = new BigDecimal(10);
        // 推荐使用
        BigDecimal bigDecimal2 = new BigDecimal("10.123");
        // 不推荐 会丢失精确度
        BigDecimal bigDecimal3 = new BigDecimal(10.123);
        System.out.println("输出bigDecimal1:"+bigDecimal1);
        System.out.println("输出bigDecimal2:"+bigDecimal2);
        System.out.println("输出bigDecimal3:"+bigDecimal3);
    }

结果输出:  

 1.2、BigDecimal还提供默认值创建(0、1、10)

  public static void main(String[] args) {
        // 创建默认为0
        BigDecimal bigDecimal1 =  BigDecimal.ZERO;
        // 创建默认为1
        BigDecimal bigDecimal2 = BigDecimal.ONE;
        // 创建默认为10
        BigDecimal bigDecimal3 = BigDecimal.TEN;
        System.out.println("输出bigDecimal1: "+bigDecimal1);
        System.out.println("输出bigDecimal2: "+bigDecimal2);
        System.out.println("输出bigDecimal3: "+bigDecimal3);
    }

结果输出: 

 1.3、int、long、double等,也可以这么创建实例(不推荐)

   public static void main(String[] args) {
        // 创建默认为0
        BigDecimal bigDecimal1 =  BigDecimal.valueOf(10);
        // 创建默认为1
        BigDecimal bigDecimal2 = BigDecimal.valueOf(10L);
        // 创建默认为10
        BigDecimal bigDecimal3 = BigDecimal.valueOf(10.1);
        System.out.println("输出bigDecimal1: "+bigDecimal1);
        System.out.println("输出bigDecimal2: "+bigDecimal2);
        System.out.println("输出bigDecimal3: "+bigDecimal3);
    }

 结果输出: 

 二、使用compareTo方法比较大小

        flag = -1,  表示bigDecimal1小于 bigDecimal2;
        flag = 0,   表示bigDecimal1等于bigDecimal2;
        flag = 1,   表示bigDecimal1大于bigDecimal2;

 实际应用中直接跟0比较就可以了,
    大于0就是bigDecimal1   大于  bigDecimal2
    等于0就是bigDecimal1   等于  bigDecimal2
    小于0就是bigDecimal1   小于  bigDecimal2

public static void main(String[] args) {

        BigDecimal bigDecimal1 = new BigDecimal("10");
        BigDecimal bigDecimal2 = new BigDecimal("20");
        int result = bigDecimal1.compareTo(bigDecimal2);
        System.out.println("bigDecimal1小于 bigDecimal2: " + result);
        if (bigDecimal1.compareTo(bigDecimal2) < 0) {
            System.out.println("实际使用 bigDecimal1小于 bigDecimal2");
        }

        BigDecimal bigDecimal3 = new BigDecimal("10");
        int result1 = bigDecimal1.compareTo(bigDecimal3);
        System.out.println("bigDecimal1等于bigDecimal3: " + result1);
        if (bigDecimal1.compareTo(bigDecimal3) == 0) {
            System.out.println("实际使用 bigDecimal1等于bigDecimal3 ");
        }

        BigDecimal bigDecimal4 = new BigDecimal("5");
        int result2 = bigDecimal1.compareTo(bigDecimal4);
        System.out.println("bigDecimal1大于bigDecimal4: " + result2);
        if (bigDecimal1.compareTo(bigDecimal4) > 0) {
            System.out.println("实际使用 bigDecimal1大于bigDecimal4");
        }
    }

输出结果:

三、BigDecimal设置精度  以及相应八种舍入模式 

ROUND_UP向远离零的方向舍入。舍弃非零部分,并将非零舍弃部分相邻的一位数字加一
ROUND_DOWN

向接近零的方向舍入。舍弃非零部分,同时不会非零舍弃部分相邻的一位数字加一,采取截取行为。

ROUND_CEILING向正无穷的方向舍入。如果为正数,舍入结果同ROUND_UP一致;如果为负数,舍入结果同ROUND_DOWN一致。注意:此模式不会减少数值大小。
ROUND_FLOOR向负无穷的方向舍入。如果为正数,舍入结果同ROUND_DOWN一致;如果为负数,舍入结果同ROUND_UP一致。注意:此模式不会增加数值大小。
ROUND_HALF_UP向“最接近”的数字舍入,如果与两个相邻数字的距离相等,则为向上舍入的舍入模式。
如果舍弃部分>= 0.5,则舍入行为与ROUND_UP相同;否则舍入行为与ROUND_DOWN相同。
这种模式也就是我们常说的我们的“四舍五入”。
ROUND_HALF_DOWN向“最接近”的数字舍入,如果与两个相邻数字的距离相等,则为向下舍入的舍入模式。
如果舍弃部分> 0.5,则舍入行为与ROUND_UP相同;否则舍入行为与ROUND_DOWN相同。
这种模式也就是我们常说的我们的“五舍六入”。
ROUND_HALF_EVEN向“最接近”的数字舍入,如果与两个相邻数字的距离相等,则相邻的偶数舍入。
如果舍弃部分左边的数字奇数,则舍入行为与 ROUND_HALF_UP 相同;
如果为偶数,则舍入行为与 ROUND_HALF_DOWN 相同。
注意:在重复进行一系列计算时,此舍入模式可以将累加错误减到最小。
此舍入模式也称为“银行家舍入法”,主要在美国使用。
四舍六入,被舍位为5时两种情况,如果前一位为奇数,则入位,否则舍去。
ROUND_UNNECESSARY断言请求的操作具有精确的结果,因此不需要舍入。如果对获得精确结果的操作指定此舍入模式,则抛出ArithmeticException。
   public static void main(String[] args) {

        BigDecimal bigDecimal1 = new BigDecimal("20.1252122");
        System.out.print("ROUND_UP:-->");
        System.out.println(bigDecimal1.setScale(2,BigDecimal.ROUND_UP));
        System.out.print("ROUND_DOWN:-->");
        System.out.println(bigDecimal1.setScale(2,BigDecimal.ROUND_DOWN));
        System.out.print("ROUND_CEILING:-->");
        System.out.println(bigDecimal1.setScale(2,BigDecimal.ROUND_CEILING));
        System.out.print("ROUND_FLOOR:-->");
        System.out.println(bigDecimal1.setScale(2,BigDecimal.ROUND_FLOOR));
        System.out.print("ROUND_HALF_UP:-->");
        System.out.println(bigDecimal1.setScale(2,BigDecimal.ROUND_HALF_UP));
        System.out.print("ROUND_HALF_DOWN:-->");
        System.out.println(bigDecimal1.setScale(2,BigDecimal.ROUND_HALF_DOWN));
        System.out.print("ROUND_HALF_EVEN:-->");
        System.out.println(bigDecimal1.setScale(2,BigDecimal.ROUND_HALF_EVEN));
        System.out.print("ROUND_UNNECESSARY:-->");
        System.out.println(bigDecimal1.setScale(BigDecimal.ROUND_UNNECESSARY));
    }

结果输出

注意点: 

ROUND_UNNECESSARY断言请求的操作具有精确的结果,因此不需要舍入。

如果对获得精确结果的操作指定此舍入模式,则抛出ArithmeticException。

 

四、基本使用(加、减、乘、除)

   public static void main(String[] args) {

        BigDecimal bigDecimal1 = new BigDecimal("20");
        BigDecimal bigDecimal2 = new BigDecimal("10");
        System.out.print("加-->" + bigDecimal1 + "+" + bigDecimal2 + "=");
        System.out.println(bigDecimal1.add(bigDecimal2));

        System.out.print("减-->" + bigDecimal1 + "-" + bigDecimal2 + "=");
        System.out.println(bigDecimal1.subtract(bigDecimal2));

        System.out.print("乘-->" + bigDecimal1 + "*" + bigDecimal2 + "=");
        System.out.println(bigDecimal1.multiply(bigDecimal2));

        System.out.print("除-->" + bigDecimal1 + "/" + bigDecimal2 + "=");
        System.out.println(bigDecimal1.divide(bigDecimal2));

    }

结果输出:

注意点:除法小数点过多会报错 示例:

   public static void main(String[] args) {

        BigDecimal bigDecimal1 = new BigDecimal("20");
        BigDecimal bigDecimal2 = new BigDecimal("10.00212");
        
        System.out.println(bigDecimal1.divide(bigDecimal2));

    }

 结果输出:

 出现当前异常的原因在于 BigDecimal 是不可变的、任意精度的有符号十进制数,所以可以做精确计算。但在除法中,准确的商可能是一个无限长的十进制扩展;例如,1 除以 3 所得的商。我们在做除法时,没有指定舍入模式,并且无法表示为准确的结果,因此抛出了这个异常(java.lang.ArithmeticException)。

 了解问题所在我们只需要在 divide() 方法中传入 MathContext 对象或 RoundingMode 对象,指定精度和舍入模式就可以解决该问题

  public static void main(String[] args) {

        BigDecimal bigDecimal1 = new BigDecimal("20");
        BigDecimal bigDecimal2 = new BigDecimal("10.00212");
        BigDecimal divide = bigDecimal1.divide(bigDecimal2, 2, BigDecimal.ROUND_HALF_DOWN);
        System.out.println(divide);

    }

结果输出:

 五、BigDecimal其他方法

abs()求绝对值,不管正数还是负数,都得到正数
negate()求相反数,正变负,负变正
pow(int n)求乘方,如BigDecimal.valueOf(2).pow(3)的值为8
max(BigDecimal val)两值比较,返回最大值
min(BigDecimal val)两值比较,返回最小值
 public static void main(String[] args) {
        BigDecimal bigDecimal1 = new BigDecimal("-20");
        System.out.println("求绝对值-->" + bigDecimal1.abs()); // 求绝对值
        System.out.println("求相反数-->" + bigDecimal1.negate()); // 求相反数
        System.out.println("求乘方-->" + bigDecimal1.pow(2));//求乘方
        System.out.println("最大值-->" + bigDecimal1.max(new BigDecimal(10)));//两值比较,返回最大值
        System.out.println("最小值-->" + bigDecimal1.min(new BigDecimal(15)));//两值比较,返回最小值

    }

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值