• 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));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    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));
      
      • 1
      • 2
      • 3
      • 4
      • 5
    • 两个都是字串:都转为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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    附录:补充 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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    坑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会忽略精度
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    其他

    这些问题请自行再研究

    • 关于BigDecimal 的格式化问题(百分比、保留小数位数、货币…)
    • 关于BigDecimal的加减乘除运算问题、除0的问题
  • 相关阅读:
    Golang抓包:实现网络数据包捕获与分析
    个人整理前端代码规范
    Hbase,Hive和Hdfs的关系以及区别
    免费 Copilot 用户可以访问 OpenAI 的 GPT-4 Turbo;面向 3D 虚拟环境的多面手 AI 代理
    mac配置hdc
    java基础知识三
    开源大赛的种种收获
    Linux常用基本命令大全
    Apollo 应用与源码分析:Monitor监控-硬件监控-GPS
    [BPU部署教程] 一文带你轻松走出模型部署新手村
  • 原文地址:https://blog.csdn.net/w8y56f/article/details/126691416