相信Bigdecimal这个类大家或多或少都在开发中用过,因为也不是经常用,所以对其中的一些细节或者坑不是很清楚,但是要用的时候总感觉对里面的知识点有点模糊,所以这次就做一下整理,方便以后查阅
一、构造方法的大坑
JDK提供了好几种构造方法,但是平时使用的时候一般只有参与运算的可能是小数且需要精度运算的时候,才会用到Bigdecimal,所以通常来说,下面这两个构造方法可能最常用到
// 传入double
public BigDecimal(double val) {
this(val,MathContext.UNLIMITED);
}
// 传入字符串
public BigDecimal(String val) {
this(val.toCharArray(), 0, val.length());
}
这里就有一个大坑,就是传入double类型的浮点数创建Bigdecimal对象并不是你希望的值
可以看下面这段代码
public static void main(String[] args) {
BigDecimal bigDecimal1 = new BigDecimal("0.1");
BigDecimal bigDecimal2 = new BigDecimal(0.1);
System.out.println(bigDecimal1.compareTo(bigDecimal2));
System.out.println(bigDecimal1);
System.out.println(bigDecimal2);
}
我们可以清楚的看到,两个构造方法生成的Bigdecimal并不相等,这是因为浮点数本身就是不精确的,直接传入double,就会导致Bigdecimal也不精确
那假如说我的入参是对方强制传入的,那有没有什么办法呢?
有的,先将double转成字符串,再转成Bigdecimal
public static void main(String[] args) {
BigDecimal bigDecimal1 = new BigDecimal("0.1");
BigDecimal bigDecimal2 = new BigDecimal(Double.toString(0.1));
System.out.println(bigDecimal1.compareTo(bigDecimal2));
System.out.println(bigDecimal1);
System.out.println(bigDecimal2);
}
二、四则运算API
这里只列举加减乘除这四则运算API,主要是记录方法名,方便使用时记得调哪个方法
加法
public BigDecimal add(BigDecimal augend) {}
减法
public BigDecimal subtract(BigDecimal subtrahend) {}
乘法
public BigDecimal multiply(BigDecimal multiplicand) {}
除法
public BigDecimal divide(BigDecimal divisor) {}
值得说明的是除法运算,如果直接调用上面的除法API,在遇到除不尽的情况下,是会出现异常的,所以在实际使用时,会设置保留位数,以及取舍方式,也即是下面这两种API
// divisor 被除数
// scale 保留几位小数
// RoundingMode 取舍方式的枚举
public BigDecimal divide(BigDecimal divisor, int scale, RoundingMode roundingMode) {}
// divisor 被除数
// scale 保留几位小数
// RoundingMode 取舍方式的枚举数字值
public BigDecimal divide(BigDecimal divisor, int scale, int roundingMode) {}
三、取舍方式
从上一节我们可以看到,Bigdecimal将取舍方式做成了RoundingMode的枚举
public enum RoundingMode {
UP(BigDecimal.ROUND_UP),
DOWN(BigDecimal.ROUND_DOWN),
CEILING(BigDecimal.ROUND_CEILING),
FLOOR(BigDecimal.ROUND_FLOOR),
HALF_UP(BigDecimal.ROUND_HALF_UP),
HALF_DOWN(BigDecimal.ROUND_HALF_DOWN),
HALF_EVEN(BigDecimal.ROUND_HALF_EVEN),
UNNECESSARY(BigDecimal.ROUND_UNNECESSARY);
}
1、ROUND_UP(数字代表,0)
ROUND_UP的含义是背零取整,即在坐标轴上,尽可能的以背离0的方向取整,我们可以看注释中给出的示例
5.5 >>>>>>>>>>>>>>>> 6
-5.5 >>>>>>>>>>>>>>>> -6
2、ROUND_DOWN(数字代表,1)
ROUND_DOWN与ROUND_UP含义相反,是向零取整,即在坐标轴上,尽可能的以靠近0的方向取整,我们可以看注释中给出的示例
5.5 >>>>>>>>>>>>>>>> 5
-5.5 >>>>>>>>>>>>>>>> -5
3、ROUND_CEILING(数字代表,2)
ROUND_CEILING的含义是进1取整,即是在最标轴上,向右取整,如果数字为正,效果等同于远零取整,如果为负,则等同于近零取整,我们看一下注释中给出的示例
5.5 >>>>>>>>>>>>>>>> 6
-5.5 >>>>>>>>>>>>>>>> -5
4、ROUND_FLOOR(数字代表,3)
ROUND_FLOOR的含义和ROUND_CEILING相反,是舍尾取整,即是在坐标轴上,向左取整,如果数字为正,效果等同于向零取整,如果为负,则等同于背零取整
5.5 >>>>>>>>>>>>>>>> 5
-5.5 >>>>>>>>>>>>>>>> -6
5、ROUND_HALF_UP(数字代表,4)
ROUND_HALF_UP的含义是我们通常理解的四舍五入,这个没什么好说的,直接看示例
5.5 >>>>>>>>>>>>>>>> 6
1.1 >>>>>>>>>>>>>>>> 1
-1.1 >>>>>>>>>>>>>>>> -1
-5.5 >>>>>>>>>>>>>>>> -6
6、ROUND_HALF_DOWN(数字代表,5)
ROUND_HALF_DOWN的含义跟ROUND_HALF_UP差不多,不过它是五舍六入,区别就在于等于5时是舍去而不是进一,还是看一下示例
5.5 >>>>>>>>>>>>>>>> 5
1.6 >>>>>>>>>>>>>>>> 2
-1.6 >>>>>>>>>>>>>>>> -2
-5.5 >>>>>>>>>>>>>>>> -5
7、ROUND_HALF_EVEN(数字代表,6)
ROUND_HALF_EVEN有点像ROUND_HALF_UP和ROUND_HALF_DOWN,区别还是在等于5的时候,它是向偶数靠近,看一下示例吧
5.5 >>>>>>>>>>>>>>>> 6
2.5 >>>>>>>>>>>>>>>> 2
1.6 >>>>>>>>>>>>>>>> 2
1.1 >>>>>>>>>>>>>>>> 1
-1.1 >>>>>>>>>>>>>>>> -1
-1.6 >>>>>>>>>>>>>>>> -2
-2.5 >>>>>>>>>>>>>>>> -2
-5.5 >>>>>>>>>>>>>>>> -6
8、UNNECESSARY(数字代表,7)
它的含义如果出现小数,直接抛出ArithmeticException的异常
四、比较
比较的话,Bigdecimal提供了几种API
1、compareTo
public int compareTo(BigDecimal val) {}
返回结果有三种,-1,0,1
返回值 | 含义 |
---|---|
-1 | 前面的数比后面的数小 |
0 | 两个数相等 |
1 | 前面的数大于后边的数 |
2、max,min
public BigDecimal min(BigDecimal val) {
return (compareTo(val) <= 0 ? this : val);
}
public BigDecimal max(BigDecimal val) {
return (compareTo(val) >= 0 ? this : val);
}
方法内本质还是调用compareTo方法,不过是做了层封装
五、总结
本篇文章只简单列举了Bigdecimal的构造方法,四则运算API,取舍方式,以及两个数之间的比较等少量内容,还有包括像格式化等API没有介绍,但是那些在实际开发中并不常用,如果后面有这个需求的话,可以再接着整理