使用BigDecimal需要避免的坑
使用BigDecimal需要避免的坑
1.直接用浮点数初始化
2 加减乘除时不设精度
3 用 equals 判断相等
4 使用 scale 时忽视实际含义
5 忽略不可变性
6 忽视性能问题
package com.example.core.mydemo.java3; import java.math.BigDecimal; import java.math.RoundingMode; /** * link: https://www.cnblogs.com/oktokeep/p/18350065 * BigDecimal加减乘除运算,保留2位小数点,初始化,与0的比较 */ public class BigDecimalTest { public static void main(String[] args) { //1.直接用浮点数初始化 BigDecimal num = new BigDecimal(0.1); System.out.println(num); //0.1000000000000000055511151231257827021181583404541015625 //注意:永远不要用 BigDecimal(double) 构造函数,用字符串或整数更靠谱。也可以使用BigDecimal.valueOf()函数。 BigDecimal num2 = new BigDecimal("0.1"); System.out.println(num2); //0.1 //2 加减乘除时不设精度 BigDecimal a = new BigDecimal("1.03"); BigDecimal b = new BigDecimal("0.42"); //减法 BigDecimal result = a.subtract(b); System.out.println(result); //0.61 BigDecimal c = new BigDecimal("10"); BigDecimal d = new BigDecimal("3"); // BigDecimal result2 = c.divide(d); // System.out.println(result2); //报错了 Non-terminating decimal expansion; no exact representable decimal result. //报错的根本原因:10/3 是无限小数,BigDecimal 默认不保留小数点后面,精度溢出。 //注意: 在BigDecimal 做除法时 ,必须指定精度。 BigDecimal result3 = c.divide(d, 2, RoundingMode.HALF_UP); System.out.println(result3); //3 用 equals 判断相等 BigDecimal x = new BigDecimal("1.0"); BigDecimal y = new BigDecimal("1.00"); System.out.println(x.equals(y)); //false 尽管 1.0 和 1.00 的数值相等,但精度不一样,equals 判定为不同。 //优化方法,用 compareTo 比较数值: System.out.println(x.compareTo(y) == 0); //4 使用 scale 时忽视实际含义 BigDecimal num3 = new BigDecimal("123.45000"); System.out.println(num3.scale()); //5 BigDecimal stripped = num3.stripTrailingZeros(); System.out.println(stripped.scale()); //2 //明确 scale 的含义。 我们不要混淆 scale(刻度) 和 precision(精度),必要时显式设置小数位数。 BigDecimal fixed = num3.setScale(2, RoundingMode.HALF_UP); System.out.println(fixed); //5 忽略不可变性 BigDecimal sum = new BigDecimal("0"); for (int i = 0; i < 5; i++) { sum.add(new BigDecimal("1")); } // 问题原因是 add 方法不会改变原对象,而是返回一个新的 BigDecimal 实例. System.out.println(sum); //0 //用变量接住返回值。 BigDecimal sum2 = new BigDecimal("0"); for (int i = 0; i < 5; i++) { sum2 = sum2.add(new BigDecimal("1")); } //BigDecimal 操作后需要接住新实例。 System.out.println(sum2); //5 //6 忽视性能问题 BigDecimal principal = new BigDecimal("10000"); BigDecimal rate = new BigDecimal("0.05"); BigDecimal interest = principal.multiply(rate); System.out.println(interest); //500.00 //能用整数就用整数(比如分代替元)。 //批量计算时,用 double 计算,结果最后转换成 BigDecimal。 //参与大批量计算时,两个BigDecimal对象直接计算会比较慢,尽量少用,能优化的地方别放过。 double principal2 = 10000; double rate2 = 0.05; BigDecimal interest2 = BigDecimal.valueOf(principal2 * rate2); System.out.println(interest2); } }