我的编程空间,编程开发者的网络收藏夹
学习永远不晚

为什么要禁止使用BigDecimal的equals方法做等值比较

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

为什么要禁止使用BigDecimal的equals方法做等值比较

本文小编为大家详细介绍“为什么要禁止使用BigDecimal的equals方法做等值比较”,内容详细,步骤清晰,细节处理妥当,希望这篇“为什么要禁止使用BigDecimal的equals方法做等值比较”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。

BigDecimal 很多人应该听说过它,也知道它的用法,它是java.math包中提供的一种可以用来进行精确运算的类型。

很多人都知道,在进行金额表示、金额计算等场景,不能使用doublefloat等类型,而是要使用对精度支持的更好的BigDecimal

所以,很多支付、电商、金融等业务中,BigDecimal的使用非常频繁。而且不得不说这是一个非常好用的类,其内部自带了很多方法,如加,减,乘,除等运算方法都是可以直接调用的。

除了需要用BigDecimal表示数字和进行数字运算以外,代码中还经常需要对于数字进行相等判断。

那么,为什么会有这样的要求呢?背后的思考是什么呢?

其实,我在之前的CodeReview中,看到过以下这样的低级错误:

if(bigDecimal == bigDecimal1){    // 两个数相等}

这种错误,相信聪明的读者一眼就可以看出问题,因为BigDecimal是对象,所以不能用==来判断两个数字的值是否相等。

以上这种问题,在有一定的经验之后,还是可以避免的,但是聪明的读者,看一下以下这行代码,你觉得他有问题吗:

if(bigDecimal.equals(bigDecimal1)){    // 两个数相等}

可以明确的告诉大家,以上这种写法,可能得到的结果和你预想的不一样!

先来做个实验,运行以下代码:

BigDecimal bigDecimal = new BigDecimal(1);BigDecimal bigDecimal1 = new BigDecimal(1);System.out.println(bigDecimal.equals(bigDecimal1));BigDecimal bigDecimal2 = new BigDecimal(1);BigDecimal bigDecimal3 = new BigDecimal(1.0);System.out.println(bigDecimal2.equals(bigDecimal3));BigDecimal bigDecimal4 = new BigDecimal("1");BigDecimal bigDecimal5 = new BigDecimal("1.0");System.out.println(bigDecimal4.equals(bigDecimal5));

以上代码,输出结果为:

truetruefalse

BigDecimal的equals原理

通过以上代码示例,我们发现,在使用BigDecimalequals方法对1和1.0进行比较的时候,有的时候是 true(当使用 int、double 定义 BigDecimal 时),有的时候是 false(当使用 String 定义 BigDecimal时)。

那么,为什么会出现这样的情况呢,我们先来看下BigDecimalequals方法。

在BigDecimal的JavaDoc中其实已经解释了其中原因:

Compares this  BigDecimal with the specified Object for equality.  Unlike compareTo, this method considers two BigDecimal objects equal only if they are equal in value and scale (thus 2.0 is not equal to 2.00 when compared by  this method)

大概意思就是,equals方法和compareTo并不一样,equals方法会比较两部分内容,分别是值(value)和精度(scale)

所以,我们以上代码定义出来的两个BigDecimal对象(bigDecimal4和bigDecimal5)的精度是不一样的,所以使用equals比较的结果就是false了。

尝试着对代码进行debug,在debug的过程中我们也可以看到bigDecimal4的精度是0,而bigDecimal5的精度是1。

到这里,我们大概解释清楚了,之所以equals比较bigDecimal4bigDecimal5的结果是 false ,是因为精度不同。

那么,为什么精度不同呢?为什么bigDecimal2bigDecimal3的精度是一样的(当使用int、double定义BigDecimal时),而bigDecimal4bigDecimal5却不一样(当使用String定义BigDecimal时)呢?

为什么精度不同

这个就涉及到BigDecimal的精度问题了,这个问题其实是比较复杂的,由于不是本文的重点,这里面就简单介绍一下吧。大家感兴趣的话,后面单独讲。

首先,BigDecimal一共有以下4个构造方法:

  1. BigDecimal(int)

  2. BigDecimal(double)

  3. BigDecimal(long)

  4. BigDecimal(String)

以上四个方法,创建出来的的BigDecimal的精度是不同的。

BigDecimal(long) 和BigDecimal(int)

首先,最简单的就是BigDecimal(long) 和BigDecimal(int),因为是整数,所以精度就是0

public BigDecimal(int val) {    this.intCompact = val;    this.scale = 0;    this.intVal = null;}public BigDecimal(long val) {    this.intCompact = val;    this.intVal = (val == INFLATED) ? INFLATED_BIGINT : null;    this.scale = 0;}

BigDecimal(double)

而对于BigDecimal(double) ,当我们使用new BigDecimal(0.1)创建一个BigDecimal 的时候,其实创建出来的值并不是正好等于0.1的,而是0.1000000000000000055511151231257827021181583404541015625 。这是因为doule自身表示的只是一个近似值。

那么,无论我们使用new BigDecimal(0.1)还是new BigDecimal(0.10)定义,他的近似值都是0.1000000000000000055511151231257827021181583404541015625这个,那么他的精度就是这个数字的位数,即55。

其他的浮点数也同样的道理。对于new BigDecimal(1.0)这样的形式来说,因为他本质上也是个整数,所以他创建出来的数字的精度就是0。

所以,因为BigDecimal(1.0)BigDecimal(1.00)的精度是一样的,所以在使用equals方法比较的时候,得到的结果就是 true。

BigDecimal(string)

而对于BigDecimal(double)当我们使用new BigDecimal("0.1")创建一个BigDecimal 的时候,其实创建出来的值正好就是等于0.1的。那么他的精度也就是1。

如果使用new BigDecimal("0.10000"),那么创建出来的数就是0.10000,精度也就是5。

所以,因为BigDecimal("1.0")和BigDecimal("1.00")的精度不一样,所以在使用equals方法比较的时候,得到的结果就是false。

如何比较BigDecimal

前面,我们解释了BigDecimalequals方法,其实不只是会比较数字的值,还会对其精度进行比较。

所以,当我们使用equals方法判断判断两个数是否相等的时候,是极其严格的。

那么,如果我们只想判断两个BigDecimal的值是否相等,那么该如何判断呢?

BigDecimal中提供了compareTo方法,这个方法就可以只比较两个数字的值,如果两个数相等,则返回0。

    BigDecimal bigDecimal4 = new BigDecimal("1");    BigDecimal bigDecimal5 = new BigDecimal("1.0000");    System.out.println(bigDecimal4.compareTo(bigDecimal5));

以上代码,输出结果:

0

读到这里,这篇“为什么要禁止使用BigDecimal的equals方法做等值比较”文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注编程网行业资讯频道。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

为什么要禁止使用BigDecimal的equals方法做等值比较

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

为什么要禁止使用BigDecimal的equals方法做等值比较

本文小编为大家详细介绍“为什么要禁止使用BigDecimal的equals方法做等值比较”,内容详细,步骤清晰,细节处理妥当,希望这篇“为什么要禁止使用BigDecimal的equals方法做等值比较”文章能帮助大家解决疑惑,下面跟着小编的
2023-06-27

为什么禁止使用BigDecimal的equals方法做等值比较

本篇内容介绍了“为什么禁止使用BigDecimal的equals方法做等值比较”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!BigDecim
2023-06-16

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录