BigDecimal 详解
Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算。
BigDecimal表示功能强大小数的意思,Decimal翻译是小数的。
BigDecimal所创建的是对象,故我们不能使用传统的+、-、*、/等算术运算符直接对其对象进行数学运算,而必须调用其相对应的方法。
1、能对数据小数部分保留小数后面固定位数,并且进行不同模式的舍去操作
2、对数据进行加减乘除等数据操作
3、能判断该数值的位数(小数点前后的),数值的小数位数
4、两个数值进行比较
BigDecimal(int|double|long|char[]|String in)
BigDecimal bigDecimal = new BigDecimal("123.456");
System.out.println("bigDecimal 123.456 string =" + bigDecimal);
bigDecimal = new BigDecimal(123.456);
System.out.println("bigDecimal 123.456 float =" + bigDecimal);
bigDecimal = new BigDecimal(123);
System.out.println("bigDecimal 123 int =" + bigDecimal);
bigDecimal 123.456 string =123.456
bigDecimal 123.456 float =123.4560000000000030695446184836328029632568359375
bigDecimal 123 int =123
由此可以看出,BigDecimal对象,如果有小数的情况,
如果不对小数位数进行控制,小数后面的位数是不可控的。
BigDecimal(int|double|long|char[]|String in, MathContext mc)
其中MathContext是一个数据规则对象,可以该数值显示的最多位数和四舍五入规则。
比如:MathContext mc = new MathContext(5, RoundingMode.HALF_UP);
第一个参数表示,该数值最多显示的位数,
第二个参数表示,改数值舍入舍出的模式,RoundingMode.HALF_UP表示四舍五入,RoundingMode.DOWN表示舍去
数值舍入舍出的模式还有其他六种模式,详情请看:https://blog.csdn.net/wenzhi20102321/article/details/104725470
MathContext mc = new MathContext(5, RoundingMode.HALF_UP);
BigDecimal bigDecimal = new BigDecimal("123.456", mc);
System.out.println("bigDecimal 123.456 string =" + bigDecimal);
bigDecimal = new BigDecimal(123.456, mc);
System.out.println("bigDecimal 123.456 float =" + bigDecimal);
bigDecimal = new BigDecimal(123, mc);
System.out.println("bigDecimal 123 int =" + bigDecimal);
bigDecimal 123.456 string =123.46
bigDecimal 123.456 float =123.46
bigDecimal 123 int =123
如果规则对象修改为如下:
MathContext mc = new MathContext(2, RoundingMode.HALF_UP);
bigDecimal 123.456 string =1.2E+2
bigDecimal 123.456 float =1.2E+2
bigDecimal 123 int =1.2E+2
上面是科学计数法,表示1.2乘以10的两次方。
BigDecimal方法也是可以通过方法setScale(int scale, int roundingMode)
设置小数点后面位数和控制舍入舍出模式
BigDecimal(BigInteger val)
BigDecimal(char[] in, int offset, int len)
BigDecimal(BigInteger unscaledVal, int scale, MathContext mc)
BigDecimal对象中的值相加,返回BigDecimal对象
BigDecimal对象中的值相减,返回BigDecimal对象
BigDecimal对象中的值相乘,返回BigDecimal对象
BigDecimal对象中的值相除,返回BigDecimal对象
将BigDecimal对象中的值转换对应类型数据
int a = bigdemical.compareTo(bigdemical2)
返回结果分析:
a = -1,表示bigdemical小于bigdemical2;
a = 0,表示bigdemical等于bigdemical2;
a = 1,表示bigdemical大于bigdemical2;
第一个参数newScale表示设置小数点后面几位数,如果不够就补零,要舍弃就按后面的规则处理
第二个参数roundingMode,表示舍入舍出模式值,RoundingMode.HALF_UP表示四舍五入,RoundingMode.DOWN表示舍去
BigDecimal bigDecimal = new BigDecimal("123.456").setScale(2, BigDecimal.ROUND_HALF_UP); //四舍五入
System.out.println("bigDecimal 123.456 string =" + bigDecimal);
bigDecimal = new BigDecimal(123.456).setScale(2, BigDecimal.ROUND_DOWN); //直接舍去
System.out.println("bigDecimal 123.456 float =" + bigDecimal);
bigDecimal = new BigDecimal(123).setScale(2, BigDecimal.ROUND_HALF_UP);
System.out.println("bigDecimal 123 int =" + bigDecimal);
bigDecimal 123.456 string =123.46
bigDecimal 123.456 float =123.45
bigDecimal 123 int =123.00
setScale方法在BigDecimal还是比较重要的,因为小数默认是有很多位的,
如果不进行精度设置显示小数位数是不确定的。
setScale还有包含设置数据规则对象的参数方法:
setScale(int newScale, RoundingMode roundingMode)
如下代码:
BigDecimal bigDecimal = new BigDecimal(123).setScale(2, BigDecimal.ROUND_HALF_UP);
System.out.println("bigDecimal 123 int setScale 2 =" + bigDecimal);
System.out.println("bigDecimal 123 precision =" + bigDecimal.precision());
System.out.println("bigDecimal 123 scale =" + bigDecimal.scale());
bigDecimal = new BigDecimal(123.456);
System.out.println("bigDecimal 123.456 float setScale 2 =" + bigDecimal);
System.out.println("bigDecimal 123.456 precision =" + bigDecimal.precision());
System.out.println("bigDecimal 123.456 scale =" + bigDecimal.scale());
bigDecimal = new BigDecimal(0.456);
System.out.println("bigDecimal 123.456 float =" + bigDecimal);
System.out.println("bigDecimal 123.456 precision =" + bigDecimal.precision());
System.out.println("bigDecimal 123.456 scale =" + bigDecimal.scale());
bigDecimal = new BigDecimal(0.45600);
System.out.println("bigDecimal 0.45600 float =" + bigDecimal);
System.out.println("bigDecimal 0.45600 precision =" + bigDecimal.precision());
System.out.println("bigDecimal 0.45600 scale =" + bigDecimal.scale());
运行结果:
bigDecimal 123 int setScale 2 =123.00
bigDecimal 123 precision =5
bigDecimal 123 scale =2
bigDecimal 123.456 float =123.4560000000000030695446184836328029632568359375
bigDecimal 123.456 precision =49
bigDecimal 123.456 scale =46
bigDecimal 123.456 float =0.456000000000000016431300764452316798269748687744140625
bigDecimal 123.456 precision =54
bigDecimal 123.456 scale =54
bigDecimal 0.45600 float =0.456000000000000016431300764452316798269748687744140625
bigDecimal 0.45600 precision =54
bigDecimal 0.45600 scale =54
分析:
1、precision()方法是获取小数点前后数值的位数,但是整数是零的情况,整数位不算入内。
2、scale()方法是获取数值小数的位数,不进行小数位设置的情况,获取的值是不定的。
3、precision() - scale() 即可获取整数的位数,如果小于等于0,表示个位为零,并且该数值不大于1。
divideAndRemainder方法的结果是一个BigDecimal数组,
第一个数组值是调用者/divisor ,所得的商
第二个数组值是调用者%divisor ,所得的余数
BigDecimal bigDecimal = new BigDecimal(123.22).setScale(2, BigDecimal.ROUND_HALF_UP);
System.out.println("bigDecimal 123.22 setScale 2 =" + bigDecimal);
BigDecimal[] bigDecimals = bigDecimal.divideAndRemainder(new BigDecimal(5));
System.out.println("bigDecimal 123.22/5 bigDecimals[0] setScale 2 =" + bigDecimals[0]);
System.out.println("bigDecimal 123.22/5 bigDecimals[1] setScale 2 =" + bigDecimals[1]);
System.out.println("==================================================================");
bigDecimal = new BigDecimal(123.22);
bigDecimals = bigDecimal.divideAndRemainder(new BigDecimal(5));
System.out.println("bigDecimal 123.22/5 bigDecimals[0] =" + bigDecimals[0]);
System.out.println("bigDecimal 123.22/5 bigDecimals[1] =" + bigDecimals[1]);
System.out.println("==================================================================");
bigDecimal = new BigDecimal(123.22);
bigDecimals = bigDecimal.divideAndRemainder(new BigDecimal(5),new MathContext(4,RoundingMode.HALF_UP));
System.out.println("bigDecimal 123.22/5 bigDecimals[0] MathContext 4 =" + bigDecimals[0]);
System.out.println("bigDecimal 123.22/5 bigDecimals[1] MathContext 4 =" + bigDecimals[1]);
运行结果:
bigDecimal 123.22 setScale 2 =123.22
bigDecimal 123.22/5 bigDecimals[0] setScale 2 =24.00
bigDecimal 123.22/5 bigDecimals[1] setScale 2 =3.22
==================================================================
bigDecimal 123.22/5 bigDecimals[0] =24.000000000000000000000000000000000000000000000
bigDecimal 123.22/5 bigDecimals[1] =3.219999999999998863131622783839702606201171875
==================================================================
bigDecimal 123.22/5 bigDecimals[0] MathContext 4 =24.00
bigDecimal 123.22/5 bigDecimals[1] MathContext 4 =3.219999999999998863131622783839702606201171875
方法介绍格式:返回的数据类型 方法名
1、BigDecimal abs()
返回BigDecimal其值是this的绝对值BigDecimal,其标度是的 this.scale()。
2、BigDecimal abs(MathContext mc)
返回BigDecimal其值为this的绝对值的BigDecimal,并根据上下文设置进行舍入。
3、boolean equals(Object x)
将其BigDecimal与指定 Object的相等性进行比较。
4、BigDecimal max(BigDecimal val)
返回此BigDecimal和的最大值val。
5、BigDecimal min(BigDecimal val)
返回此BigDecimal和 的最小值val。
6、BigDecimal movePointLeft(int n)
返回一个BigDecimal等于此值的小数点n向左移动的a。
7、BigDecimal movePointRight(int n)
返回一个BigDecimal等于此值的小数点n向右移动的a。
8、BigDecimal negate()
返回BigDecimal其值为(-this),其标度为的this.scale()。
9、BigDecimal pow(int n)
返回BigDecimal其值为 (this n),精确地计算出幂,并且精度不受限制。
10、BigDecimal scaleByPowerOfTen(int n)
返回其数值等于(this* 10 n)的BigDecimal
11、BigDecimal stripTrailingZeros()
返回一个BigDecimal从数字上等于该数字的a ,但从表示形式中删除了所有尾随零。
12、String toEngineeringString()
BigDecimal如果需要指数,则使用工程符号返回this的字符串表示形式。
13、String toPlainString()
返回BigDecimal 不带指数字段的字符串表示形式。
要进行setScale小数位数控制,否则小数的位数是不确定的。
java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result
原因分析:
? 通过BigDecimal的divide方法进行除法时当不整除,出现无限循环小数时,
就会抛异常:java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
解决方法:
? divide方法设置精确的小数点,如:divide(xxxxx,2)
如果想详细看其他BigDecimal方法可以上官网看,或者下载api文档查看。
java1.8 api文档下载:https://download.csdn.net/download/wenzhi20102321/9619913