本文已参与「新人创作礼」活动,一起开启掘金创作之路。
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小数位数多将采用科学计数法,构造方法形式会去除小数点后多余的0toPlainString字符串数字,构造方法形式会去除小数点后多余的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