Java 中如何比较两个BigDecimal 以及BigDecimal的坑

Java 中如何比较两个BigDecimal 以及BigDecimal的坑

一、背景

我们经常要比较两个数字是否相等,两个数字可以是整数、小数,我们也知道浮点数如float、double在java里是不准确的,那就会使用到BigDecimal来比较,那有些坑就必须先理清楚。

结论

  • 构造BigDecimal用 new BigDecimal(String) 或 BigDecimal.valueOf
  • 比较两个BigDecimal用 b1.compareTo(b2) == 0
  • 如果其中一个或两个都是字符串,则转为BigDecimal后进行比较

二、详细实验

1. 如何构造 BigDecimal

构造器有很多,用用 new BigDecimal(String) 或 BigDecimal.valueOf 来得到BigDecimal!!!不能用其他如int/long/double的构造器。否则可能会出现坑,见"坑1"

// 正例
BigDecimal b1 = new BigDecimal("0.1");
// 反例
BigDecimal b2 = new BigDecimal(0.1);

// 正例
double d = 0.1;// 比如接口传入或库中查出的值是非字符串,如何构造?
BigDecimal b1 = BigDecimal.valueOf(d);

// 【补充】:BigDecimal.valueOf 的底层用的就是字符串的构造器
public static BigDecimal valueOf(double val) {
  // Reminder: a zero double returns '0.0', so we cannot fastpath
  // to use the constant ZERO.  This might be important enough to
  // justify a factory approach, a cache, or a few private
  // constants, later.
  return new BigDecimal(Double.toString(val));
}
2. 如何比较两个BigDecimal 的值(不要用equals比较!!!)

使用 compareTo() 方法,不要用equals!!!

BigDecimal b1 = new BigDecimal("1.0");
BigDecimal b2 = new BigDecimal("1.00");

// 正例
System.out.println(b1.compareTo(b2) == 0);// 等于0表示两者相等,会忽略精度
// 反例
System.out.println(b1.equals(b2));// 返回false因为两者精度不一样即使实际值一样但最终返回false
3. 如何比较String类型之间的数字的值是否相等

转为BigDecimal进行比较!不要用字符串比较!!!

  • 其中一个是字串,另一个是BigDecimal

    String value1 = "0.1";
    BigDecimal b = new BigDecimal("0.10");
    // 将String转为BigDecimal再用compareTo比较
    BigDecimal v = new BigDeimal(value1);// 要确保value1能够转为数字,如果value1是abc这样的字串会出现NumberFormatExcception
    System.out.println(b.compareTo(v));
    
  • 两个都是字串:都转为compareTo进行比较

4. 什么是 BigDecimal 的精度(Scale)

精度就是小数点后的位数(官方文档解释得很复杂…)

System.out.println(new BigDecimal("1").scale());// 0
System.out.println(new BigDecimal("1.0").scale());// 1
System.out.println(new BigDecimal("1.00").scale());// 2
System.out.println(new BigDecimal("1.010").scale());// 3
System.out.println(new BigDecimal("0").scale());// 0
System.out.println(new BigDecimal("-0").scale());// 0
System.out.println(new BigDecimal("-1").scale());// 0
System.out.println(new BigDecimal("-1.00").scale());// 2
System.out.println(new BigDecimal("-1.1").scale());// 1
附录:补充 BigDecimal 的坑
坑1:构造器的坑
BigDecimal b1 = new BigDecimal("0.1");
BigDecimal b2 = new BigDecimal(0.1);
System.out.println(b1);// 打印:0.1
System.out.println(b2);// 打印:0.1000000000000000055511151231257827021181583404541015625
System.out.println(b1.compareTo(b2));// -1,说明b1小于b2
坑2:比较要用compareTo不要用equals
BigDecimal b1 = new BigDecimal("1.0");
BigDecimal b2 = new BigDecimal("1.00");

System.out.println(b1 == b2);// false,因为是不同的对象
System.out.println(b1.equals(b2));// false,因为scale不一样
System.out.println(b1.compareTo(b2));// 0,0就是两者相等。compareTo会忽略精度

其他

这些问题请自行再研究

  • 关于BigDecimal 的格式化问题(百分比、保留小数位数、货币…)
  • 关于BigDecimal的加减乘除运算问题、除0的问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值