先介绍下BigDecimal: 属于 java.math.BigDecimal;
在我们写代码过程中有时会遇到较大数字之间的计算问题,比如金额的计算,这个时候使用浮点类型进行计算可能就不那么准确了,会损失一定的精准度.
如果要用BigDecimal 进行数学运算,不能使用+ , - ,* , /等传统运算符,而要调用其对应的方法;
很多知识是自己操作了一遍才了解,虽然不是很难的知识点.例如BigDecimal 运算,我所不了解的地方.
1, BigDecimal 初始化
// 第一种,value 数字(浮点(不推荐,因为值不精准,如下图所示))
BigDecimal num1 = new BigDecimal(5);
BigDecimal num2 = new BigDecimal(0.05);
BigDecimal num3 = new BigDecimal(-5);
// 第二种,字符串表示(推荐使用)
BigDecimal num11 = new BigDecimal("5");
BigDecimal num12 = new BigDecimal("0.05");
BigDecimal num13 = new BigDecimal("-5");
// 特殊的值(0、1、10)
BigDecimal num21 = BigDecimal.ZERO;//0
BigDecimal num22 = BigDecimal.ONE;//1
BigDecimal num23 = BigDecimal.TEN;//10
打印结果:
和普通的数据类型赋值不同,BigDecimal 需要创建对象,特殊值虽然不需要我们创建,但是在底层也是new 了对象的.
2, 四则运算
就是对BigDecimal 的方法调用
加法: add()函数 减法: subtract()函数 乘法: multiply()函数 除法: divide()函数 绝对值: abs()函数
//加法
BigDecimal result1 = num1.add(num2);
BigDecimal result11 = num11.add(num12);
//减法
BigDecimal result2 = num1.subtract(num2);
BigDecimal result12 = num11.subtract(num12);
//乘法
BigDecimal result3 = num1.multiply(num2);
BigDecimal result13 = num11.multiply(num12);
//除法
BigDecimal result4 = num2.divide(num1, 20, BigDecimal.ROUND_HALF_UP);
BigDecimal result14 = num12.divide(num11, 20, BigDecimal.ROUND_HALF_UP);
//绝对值
BigDecimal result5 = num3.abs();
BigDecimal result15 = num13.abs();
这就是推荐使用字符串创建BigDecimal 数据的原因,使用value 创建的数据计算出来的结果出入很大.
1). System.out.println()中的数字默认是double类型的,double类型小数计算不精准。
2). 使用BigDecimal类构造方法传入double类型时,计算的结果也是不精确的!
因为不是所有的浮点数都能够被精确的表示成一个double 类型值,有些浮点数值不能够被精确的表示成 double 类型值,因此它会被表示成与它最接近的 double 类型的值。必须改用传入String的构造方法。这一点在BigDecimal类的构造方法注释中有说明。
完整代码如下:
import java.math.BigDecimal;
/**
* @author mohen
* @create 2020-12-08-16:48
* @Description: com.mathDemo
*/
public class BigDecimalTest {
public static void main(String[] args) {
BigDecimal num1 = new BigDecimal(5);
BigDecimal num2 = new BigDecimal(0.05);
BigDecimal num3 = new BigDecimal(-5);
BigDecimal num11 = new BigDecimal("5");
BigDecimal num12 = new BigDecimal("0.05");
BigDecimal num13 = new BigDecimal("-5");
BigDecimal num21 = BigDecimal.ZERO;
BigDecimal num22 = BigDecimal.ONE;
BigDecimal num23 = BigDecimal.TEN;
//加法
BigDecimal result1 = num1.add(num2);
BigDecimal result11 = num11.add(num12);
//减法
BigDecimal result2 = num1.subtract(num2);
BigDecimal result12 = num11.subtract(num12);
//乘法
BigDecimal result3 = num1.multiply(num2);
BigDecimal result13 = num11.multiply(num12);
//除法
BigDecimal result4 = num2.divide(num1, 2, BigDecimal.ROUND_HALF_UP);
BigDecimal result14 = num12.divide(num11, 2, BigDecimal.ROUND_HALF_UP);
//绝对值
BigDecimal result5 = num3.abs();
BigDecimal result15 = num13.abs();
System.out.println("result1(value加法)->" + result1);
System.out.println("result11(string加法)->" + result11);
System.out.println("result2(value减法)->" + result2);
System.out.println("result12(string减法)->" + result12);
System.out.println("result3(value乘法)->" + result3);
System.out.println("result13(string乘法)->" + result13);
System.out.println("result4(value除法)->" + result4);
System.out.println("result14(string除法)->" + result14);
System.out.println("result5(绝对值)->" + result5);
System.out.println("result15(绝对值)->" + result15);
/*System.out.println("num1->" + num1);
System.out.println("num2->" + num2);
System.out.println("num3->" + num3);
System.out.println("num11->" + num11);
System.out.println("num12->" + num12);
System.out.println("num13->" + num13);
System.out.println("num21->" + num21);
System.out.println("num22->" + num22);
System.out.println("num23->" + num23);*/
}
}
除法divide()参数使用:
即为 (BigDecimal divisor 除数, int scale 精确小数位, int roundingMode 舍入模式)
使用除法需要考虑被除数的值问题,被除数在运算前应做判断
结果的保留问题,精确的小数值位数和舍入模式.
计算1÷3的结果(最后一种ROUND_UNNECESSARY在结果为无限小数的情况下会报错,ArithmeticException)
舍入模式:
1), ROUND_UP:无论后面是多少(后面是0的话除外),在绝对值的角度,始终对非零舍弃部分前面的数字+1.
2), ROUND_DOWN:无论后面是多少,都直接丢弃,不会对舍弃部分前面的数字+1
3), ROUND_CEILING:无论后面是多少(后面是0的话除外),
值为正,舍入模式与ROUND_UP相同,
值为负,舍入模式与ROUND_DOWN相同.
4), ROUND_FLOOR:无论后面是多少(后面是0的话除外),
值为正,舍入模式与ROUND_DOWN相同,
值为负,舍入模式与ROUND_UP相同.
5), ROUND_HALF_UP:在绝对值的角度舍和入,这就是我们熟识的四舍五入模式;
如果与两个相邻数字的距离相等,则为向上舍入的舍入模式。
如果舍弃部分 >= 0.5,则舍入行为与 ROUND_UP 相同;
否则舍入行为与 ROUND_DOWN 相同。
6), ROUND_HALF_DOWN:在绝对值的角度舍和入;
如果与两个相邻数字的距离相等,则为向上舍入的舍入模式。
如果舍弃部分 > 0.5,则舍入行为与 ROUND_UP 相同;
否则舍入行为与 ROUND_DOWN 相同(五舍六入)。
7), ROUND_HALF_EVEN:
如果与两个相邻数字的距离相等,则向相邻的偶数舍入。
如果舍弃部分左边的数字为奇数,则舍入行为与 ROUND_HALF_UP 相同;
如果为偶数,则舍入行为与 ROUND_HALF_DOWN 相同。
注意,在重复进行一系列计算时,此舍入模式可以将累加错误减到最小。
此舍入模式也称为“银行家舍入法”,主要在美国使用。四舍六入,五分两种情况。
如果前一位为奇数,则入位,否则舍去。
以下例子为保留小数点1位,那么这种舍入方式下的结果。
1.15->1.2
1.25->1.2
8), ROUND_UNNECESSARY: 断言请求的操作具有精确的结果,因此不需要舍入(如果对获得精确结果的操作指定此舍入模式,则抛出ArithmeticException。).
3,BigDecimal 累加
在写项目时遇到的,因为BigDecimal 中没有 += 这种累加操作,下面是使用add () 函数示列:
第一种最后得不到你想要的结果,你拿到的值还是原来的初始值.
//无效
sumIntegral.add(retailDetail.getIntegral());
//有效
sumIntegral = sumIntegral.add(retailDetail.getIntegral());
小弟才疏学浅,有问题的地方欢迎大家指正,BigDecimal 的坑先填到这了,如果对你有帮助帮忙点赞,收藏,关注走一波!
参考:
BigDecimal加减乘除计算_haiyinshushe的博客-CSDN博客_bigdecimalblog.csdn.net