BigDecimal的使用

概述

BigDecimal是Java在java.math包中提供的一个API类,主要用于对超过16位有效位的数进行精确的运算。在商业计算、金融计算等需要高精度数值处理的场景中,BigDecimal显得尤为重要。但是BigDecimal是一个对象,不能直接使用传统的+、-、*、/等算术运算符进行数学运算,而必须调用其相对应的方法。本文是对BigDecimal的简单介绍。

构造方法

BigDecimal提供了多个构造方法,以便根据不同的需求创建对象:

BigDecimal(int)

使用int创建BigDecimal对象

BigDecimal(double)

使用double创建BigDecimal对象,但需要注意的是,由于double类型的精度限制,这种方法可能会导致结果有一定的不可预知性,因此通常不推荐使用

BigDecimal(long)

使用long创建BigDecimal对象

BigDecimal(String)

使用String创建BigDecimal对象

加、减、乘、除四则运算

1. BigDecimal加法

add(BigDecimal)

2. BigDecimal减法

subtract(BigDecimal)

3. BigDecimal乘法

multiply(BigDecimal)

4. BigDecimal除法

divide(BigDecimal)

对于除法需要注意的是,除法运算时可能会出现无法除尽的情况,此时需要指定保留的小数位数和舍入模式,否则会抛出ArithmeticException异常。

一下是除法使用的3种情况:

//1.可以除尽不抛异常
new BigDecimal(1).divide(new BigDecimal(2));

//2.存在除不尽的情况抛ArithmeticException异常
new BigDecimal(1).divide(new BigDecimal(3));
//java.lang.ArithmeticException: Non-terminating decimal expansion; 
//no exact representable decimal result.

//3.传入四舍五入,保留两位有效数字
new BigDecimal(1).divide(new BigDecimal(3),2,BigDecimal.ROUND_HALF_UP);

使用示例

//计算表达式:3+4*5-6/2 = 20
BigDecimal v2 = new BigDecimal(2);
BigDecimal v3 = new BigDecimal(3);
BigDecimal v4 = new BigDecimal(4);
BigDecimal v5 = new BigDecimal(5);
BigDecimal v6 = new BigDecimal(6);
BigDecimal v = v3.add(v4.multiply(v5)).subtract(v6.divide(v2));
System.out.println(v);

需要注意的是BigDecimal加减乘除的执行顺序与它们的算数优先级无关,只和方法的调用顺序有关。

其它方法

BigDecimal比较大小

BigDecimal v2 = new BigDecimal(2);
BigDecimal v3 = new BigDecimal(3);
System.out.println(v2.compareTo(v3));

BigDecimal比较大小使用compareTo()方法,如v2.compareTo(v3):v2和v3相等返回0,v2大于v3返回1,v2小于v3返回-1。

注意不要使用equals()比较BigDecimal的大小,在进行等值比较时,由于BigDecimal的equals()方法会同时比较值的大小和精度,因此可能会与预期不符。如下面两个值会被判定为不相等。

BigDecimal v1 = new BigDecimal("1.0");
BigDecimal v2 = new BigDecimal("1.00");
System.out.println(v1.equals(v2));
//输出false

绝对值

abs()

浮点数初始化

浮点数初始化可以使用BigDecimal.valueOf(),浮点数初始化可能会又精度问题,使用BigDecimal.valueOf()方法则不会有问题,看看它的源码就知道了,实际上是内部把double类型转成了String类型,所以才能安全地初始化。

public static BigDecimal valueOf(double var0) {
    return new BigDecimal(Double.toString(var0));
}

舍入模式

BigDecimal共有8种舍入模式:

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

断言请求的操作具有精确的结果,因此不需要舍入。如果对获得精确结果的操作指定此舍入模式,则抛出异常。

总结

综上所述,BigDecimal是Java中处理高精度数值的重要工具,通过合理使用其构造方法和数学运算方法,可以满足商业计算、金融计算等场景对高精度数值处理的需求。

参考

BigDecimal的8种RoundingMode(舍入模式)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值