java BigDecimal使用
一、BigDecimal的加减乘除:
package com.cy.test.math; import java.math.BigDecimal; public class TestBigDecimal { public static void main(String[] args) { //加法 double d1 = 1.234; double d2 = 2.341; System.out.println(d1 + d2); //3.575 System.out.println(d1 * d2); //2.8887940000000003精度出问题了 System.out.println(d1 / d2); //0.5271251601879539 这个是对的 //使用BigDecimal,加法 BigDecimal b1 = new BigDecimal(Double.toString(d1)); BigDecimal b2 = new BigDecimal(Double.toString(d2)); System.out.println(b1.add(b2).doubleValue()); //3.575 //减法 System.out.println(b1.subtract(b2).doubleValue()); //-1.107 //乘法 System.out.println(b1.multiply(b2).doubleValue()); //2.888794 //除法 保留小数点后两位,四舍五入 System.out.println(b1.divide(b2, 2, BigDecimal.ROUND_HALF_UP)); //0.53 } }
二、BigDecimal转String的时候出现的精度问题:
有些两位类型的小数如double类型的,直接转化为String时,调用的是BigDecimal的toString方法,会出现精度问题。解决办法:
package com.cy.test.math; import java.math.BigDecimal; public class TestBigDecimal3 { public static void main(String[] args) { BigDecimal b1 = new BigDecimal(1.23); BigDecimal b2 = new BigDecimal(1.24); BigDecimal b3 = new BigDecimal(1.25); System.out.println(b1); System.out.println(b2); System.out.println(b3); BigDecimal plus = b1.add(b2).add(b3); //直接打印会精度失真 System.out.println(plus); System.out.println(String.valueOf(plus.floatValue())); //设置小数位数,第一个变量是小数位数,第二个变量是取舍方法(四舍五入) BigDecimal plus2 = b1.add(b2).add(b3).setScale(2, BigDecimal.ROUND_HALF_UP); System.out.println(plus2); } }
打印结果:
1.229999999999999982236431605997495353221893310546875 1.2399999999999999911182158029987476766109466552734375 1.25 3.7199999999999999733546474089962430298328399658203125 3.72 3.72
三、BigDecimal的精度问题
Because of floating point imprecision, you’re unlikely to get the value you expect from the BigDecimal(double) constructor.

例子:
package com.test.bigdecimal; import java.math.BigDecimal; public class TestBigDecimal { public static void main(String[] args) { Object object = 0.1; if (object instanceof Number) { BigDecimal result1 = new BigDecimal(((Number) object).doubleValue()); System.out.println(result1.toString()); BigDecimal result2 = BigDecimal.valueOf(((Number) object).doubleValue()); System.out.println(result2.toString()); } } }
console:
0.1000000000000000055511151231257827021181583404541015625 0.1
结论:
1.new BigDecimal(double)可能会造成精度问题。应该使用BigDecimal.valueOf(double)方法。
四、RoundingMode
参考博客:https://zhuanlan.zhihu.com/p/445959759
BigDecimal.ROUND_DOWN:直接省略多余的小数,比如1.28如果保留1位小数,得到的就是1.2
BigDecimal.ROUND_UP:直接进位,比如1.21如果保留1位小数,得到的就是1.3
BigDecimal.ROUND_HALF_UP:四舍五入,2.35保留1位,变成2.4
BigDecimal.ROUND_HALF_DOWN:四舍五入,2.35保留1位,变成2.3
后边两种的区别就是如果保留的位数的后一位如果正好是5的时候,一个舍弃掉,一个进位。
ROUND_CEILING :向正无穷方向舍入
ROUND_FLOOR :向负无穷方向舍入
ROUND_HALF_EVEN :向(距离)最近的一边舍入,如果两边(的距离)是相等时,如果保留位数是奇数,使用ROUND_HALF_UP,如果是偶数,使用ROUND_HALF_DOWN
ROUND_UNNECESSARY :计算结果是精确的,不需要舍入模式
五、divide方法说明:
package com.test.bigdecimal;
import java.math.BigDecimal;
import java.math.RoundingMode;
public class TestBigDecimal3 {
public static void main(String[] args) {
/**
* divide()方法返回的精度是this.scale() - divisor.scale()
* 如果除不尽就会报错
* doc解释:
* 返回一个BigDecimal,其值为(this / divisor),其首选标度为(this.scale() - divisor.scale());
* 如果无法表示准确的商值(因为它有无穷的十进制扩展),则抛出ArithmeticException
*/
BigDecimal dividend = new BigDecimal("100.00"); // 被除数
BigDecimal divisor = new BigDecimal("3.00"); // 除数
BigDecimal quotient = dividend.divide(divisor);
System.out.println(quotient); // 报错
/**
* divide(BigDecimal divisor, int roundingMode),除法精度保存的是分子的scale,
* 100.0只有1位精度,所以得到的结果是33.3
*/
BigDecimal dividend1 = new BigDecimal("100.0"); // 被除数
BigDecimal divisor1 = new BigDecimal("3.00"); // 除数
BigDecimal quotient1 = dividend1.divide(divisor1, BigDecimal.ROUND_HALF_UP);
System.out.println(quotient1); // 33.3
/**
* divide(BigDecimal divisor, int scale, int roundingMode),scale为给定精度
*/
BigDecimal dividend2 = new BigDecimal("100.0"); // 被除数
BigDecimal divisor2 = new BigDecimal("3.00"); // 除数
BigDecimal quotient2 = dividend2.divide(divisor2, 2, BigDecimal.ROUND_HALF_UP);
System.out.println(quotient2); // 33.33
/**
* setScale方法会改变原始BigDecimal对象的精度
*/
BigDecimal dividend3 = new BigDecimal("100.0"); // 被除数
BigDecimal divisor3 = new BigDecimal("3.00"); // 除数
BigDecimal quotient3 = dividend3.divide(divisor3, 4, BigDecimal.ROUND_HALF_UP);
System.out.println(quotient3); // 33.3333
BigDecimal quotient4 = quotient3.setScale(3, RoundingMode.HALF_UP);
System.out.println(quotient4); // 33.333
}
}
六、multiply方法说明
package com.test.bigdecimal;
import java.math.BigDecimal;
public class TestBigDecimal2 {
public static void main(String[] args) {
/**
* multiply(BigDecimal multiplicand)
* javadoc解释:
* 返回一个BigDecimal,其值为(this × multiplicand),其标度为(this.scale() + multiplicand.scale())。
*/
BigDecimal t1 = new BigDecimal("100.0");
BigDecimal t2 = new BigDecimal("0.1");
BigDecimal t3 = new BigDecimal("0.5");
BigDecimal r1 = t1.multiply(t2);
BigDecimal r2 = r1.multiply(t3);
System.out.println(r1); //10.00
System.out.println(r2); //5.000
}
}
---
浙公网安备 33010602011771号