BigDecimal使用方式实践

337 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

BigDecimal使用方式特性示例

对于Java中精确计算我们都知道可以使用BigDecimal,但是在使用BigDecimal时很多人踩坑,也包括自己。网络上常见的解决方案是将数字转String后使用字符串构造方法的形式定义BigDecimal,其实有更优的方式,在这里整理总结一下,如果能给其他猿友一些启发那是再好不过了。在我通过对源码的研究以及在实际工作中的实践,我总结了BigDecimal的定义、比较、转字符串,如有不准确的地方恳请指正。

1. 定义BigDecimal的方式

  • 静态常量 BigDecimal.ZERO, BigDecimal.ONE, BigDecimal.TEN(推荐);
  • 静态工厂方法 BigDecimal.valueOf(...)(推荐);
  • 字符串构造方法 new BigDecimal("...")(推荐);
  • 其他构造方法 new BigDecimal(...)

推荐使用BigDecimal的静态工厂方法。 其优先于构造函数方法,因为它允许重用常用的BigDecimal值。对于0,1,10推荐直接使用静态常量。其次使用字符串构造方法,double构造方法结果将不可预测。

BigDecimal zero = BigDecimal.ZERO, one = BigDecimal.ONE, ten = BigDecimal.TEN; // 0,1,10(推荐)
BigDecimal num1 = BigDecimal.valueOf(0.001); // 0.001(推荐)
BigDecimal num2 = BigDecimal.valueOf(0.001d); // 0.001(推荐)
BigDecimal num3 = BigDecimal.valueOf(0.001L); // 0.001(推荐)
BigDecimal num4 = new BigDecimal("0.001"); // 0.001
BigDecimal num5 = new BigDecimal(Double.toString(0.001)); // 0.001
// BigDecimal num = new BigDecimal(0.001); // 0.001000000000000000020816681711721685132943093776702880859375
// BigDecimal num = new BigDecimal(0.001d); // 0.001000000000000000020816681711721685132943093776702880859375

2. 比较两个BigDecimal数的方式

只比较值大小使用compareTo方法,使用equals方法必须数值与精度都相等才相等。构造方法定义的数比较时会对比小数点后多余的0

BigDecimal num1 = BigDecimal.valueOf(0.10);
BigDecimal num2 = BigDecimal.valueOf(0.10);
BigDecimal num3 = BigDecimal.valueOf(0.1);
BigDecimal num4 = BigDecimal.valueOf(0.10000);
BigDecimal num5 = new BigDecimal("0.10");
BigDecimal num6 = new BigDecimal("0.10");
BigDecimal num7 = new BigDecimal("0.1");
BigDecimal num8 = new BigDecimal("0.10000");
System.out.println(num1.equals(num2)); // true
System.out.println(num1.equals(num7)); // true
System.out.println(num1.equals(num3)); // false,num1对于num3,num4,num5,num6,num8均为false
System.out.println(num4.equals(num5)); // true
System.out.println(num4.equals(num6)); // false
System.out.println(num5.equals(num6)); // true
System.out.println(num5.equals(num7)); // false
System.out.println(num1.compareTo(num2) == 0); // true,均为true

3. 转BigDecimal为字符串对比

  • toString小数位数多将采用科学计数法,构造方法形式会去除小数点后多余的0
  • toPlainString字符串数字,构造方法形式会去除小数点后多余的0
// toString与toPlainString的区别
BigDecimal num1 = BigDecimal.valueOf(0.0000000000); // toString:0.0,   toPlainString:0.0
BigDecimal num2 = new BigDecimal("0.0000000000");   // toString:0E-10, toPlainString:0.0000000000

BigDecimal num3 = BigDecimal.valueOf(0.0000000001); // toString:1.0E-10, toPlainString:0.00000000010
BigDecimal num4 = new BigDecimal("0.0000000001");   // toString:1E-10,   toPlainString:0.0000000001

BigDecimal num5 = BigDecimal.valueOf(1.100000000);  // toString:1.1,         toPlainString:1.1
BigDecimal num6 = new BigDecimal("1.100000000");    // toString:1.100000000, toPlainString:1.100000000

BigDecimal num7 = BigDecimal.valueOf(1.010000000);  // toString:1.01,        toPlainString:1.01
BigDecimal num8 = new BigDecimal("1.010000000");    // toString:1.010000000, toPlainString:1.010000000