【Java面试进阶】谈一谈为什么禁止使用BigDecimal的equals方法做等值比较?

Java开发手册中为什么禁止使用BigDecimal的equals方法做等值比较以及为什么禁止使用double直接构造BigDecimal 阿里Java开发手册嵩山版中明确指出:1、BigDecimal的等值比较应使用compareTo()方法,而不是equals()方法equals()方法会比较值和精度(1.0与1.00返回结果为false),而compareTo()则会忽略精度2、禁止使用构造方法BigDecimal(double)的方式把double值转换为BigDecimal对象BigDecimal(double)存在精度损失风险,在精确计算或值比较的场景中可能会导致业务逻辑异常 注:博客: 霸道流氓气质的博客_优快云博客-C#,架构 阅读详情


BigDecimal是一种java.math包提供的一种可以用来进行精确运算的类型。比如在进行金额表示、金额计算等场景,不能使用double、float等类型,而是要使用对精度支持的更好的BigDecimal,而且其内部自带了很多方法,如加,减,乘,除等运算方法都是可以直接调用的。

当然除了需要用BigDecimal表示数字和进行数字运算以外,代码中还经常需要对于数字进行相等判断。但是需要注意的是:BigDecimal的等值比较应使用compareTo()方法,而不是equals()方法。这是因为BigDecimal是对象,所以不能用’=='来判断两个数字的值是否相等。

使用equals做等值比较会怎么样?

先看一段代码:

package com.seckill.secondkill;

import java.math.BigDecimal;

public class BigDecimalDemo {
    public static void main(String[] args) {
        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));
    }
}

执行结果为:

true
true
false

BigDecimal的equals原理是什么?

通过以上代码发现,在使用BigDecimal的equals方法对1和1.0进行比较的时候,有的时候是true(当使用int、double定义BigDecimal时),有的时候是false(当使用String定义BigDecimal时)。为什么出现这种情况呢?

在BigDecimal的源码中对于equals方法有这样一段注释:

     * Compares this {@code BigDecimal} with the specified
     * {@code Object} for equality.  Unlike {@link
     * #compareTo(BigDecimal) compareTo}, this method considers two
     * {@code 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的equals源码精度比较
所以示例代码中定义的两个BigDecimal对象(bigDecimal4和bigDecimal5)的标度就不一样,使用equals的结果就是false。

我们再次运行示例代码,并debug到标度比较的位置,如下所示:
debug精度比较
在比较bigDecimal4和bigDecimal5的时候其标度不同,所以结果是false。

为什么标度不同?

为什么bigDecimal2和bigDecimal3的标度是一样的(当使用int、double定义BigDecimal时),而bigDecimal4和bigDecimal5却不一样(使用String定义BigDecimal时)?

这里对标度做简单的介绍:
首先,BigDecimal一共有以下4个构造方法:

BigDecimal(int)
BigDecimal(double)
BigDecimal(long)
BigDecimal(String)

这四种方法,创建出来的BigDecimal的标度是不同的。其中:
最简单的就是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),当使用new BigDecimal(0.1)创建一个BigDecimal的时候,其实创建出来的值并不是正好等于0.1,而是0.1000000000000000055511151231257827021181583404541015625。这是因为double自身表示的只是一个近似值。

因此,无论使用new BigDecimal(0.1)还是new BigDecimal(0.10)定义,它的近似值都是0.1000000000000000055511151231257827021181583404541015625,那么它的标度就是这个数字的位数,即55.
Decimal标度浮点数
对于new BigDecimal(1.0)来说,它本质上是个整数,所以创建出来的数字的标度为0。因为new BigDecimal(1.0)和new BigDecimal(1.00)的标度一样,所以在使用equals比较的时候,结果为true。

当我们使用new BigDecimal(”0.1“)创建一个BigDecimal的时候,其实创建出来的值正好就是等于0.1,那么它的标度就是1。如果使用new BigDecimal(”0.10000“),那么创建出来的数字就是0.10000,标度就是5。因为new BigDecimal(”1.0“)和new BigDecimal(”1.00“)的标度不一样,所以在equals的时候结果为false。

如何比较BigDecimal?

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

        BigDecimal bigDecimal4 = new BigDecimal("1");
        BigDecimal bigDecimal5 = new BigDecimal("1.000");
        System.out.println(bigDecimal4.compareTo(bigDecimal5)); // 结果为0

compareTo方法的源码如下:

    /**
     * Compares this {@code BigDecimal} with the specified
     * {@code BigDecimal}.  Two {@code BigDecimal} objects that are
     * equal in value but have a different scale (like 2.0 and 2.00)
     * are considered equal by this method.  This method is provided
     * in preference to individual methods for each of the six boolean
     * comparison operators ({@literal <}, ==,
     * {@literal >}, {@literal >=}, !=, {@literal <=}).  The
     * suggested idiom for performing these comparisons is:
     * {@code (x.compareTo(y)} &lt;<i>op</i>&gt; {@code 0)}, where
     * &lt;<i>op</i>&gt; is one of the six comparison operators.
     *
     * @param  val {@code BigDecimal} to which this {@code BigDecimal} is
     *         to be compared.
     * @return -1, 0, or 1 as this {@code BigDecimal} is numerically
     *          less than, equal to, or greater than {@code val}.
     */
    @Override
    public int compareTo(BigDecimal val) {
        // Quick path for equal scale and non-inflated case.
        if (scale == val.scale) {
            long xs = intCompact;
            long ys = val.intCompact;
            if (xs != INFLATED && ys != INFLATED)
                return xs != ys ? ((xs > ys) ? 1 : -1) : 0;
        }
        int xsign = this.signum();
        int ysign = val.signum();
        if (xsign != ysign)
            return (xsign > ysign) ? 1 : -1;
        if (xsign == 0)
            return 0;
        int cmp = compareMagnitude(val);
        return (xsign > 0) ? cmp : -cmp;
    }

总结

  1. BigDecimal是一个非常好用的表示高精度数字的类,其中提供了很多丰富的方法,但是使用equals做比较的时候需要谨慎。
  2. 如果要对两个BigDecimal的数值进行比较的话,可以使用compareTo方法。

原文:《Java开发灵魂17问》

AB相增量式编码器以及STM32定时器编码器模式测速/测距离(HAL库) 编码器(Encoder)是一种用于测量旋转运动或位置的设备。编码器通常与定时器模块一起使用,以便在微控制器中获取和计算旋转的脉冲数量,从而确定物体的运动方向和距离。编码器在许多应用中都很有用,例如机器人运动控制、电机位置反馈和位置传感。STM32微控制器提供了多种类型的编码器支持,其中一种常见的编码器类型是增量编码器。增量编码器基于两个脉冲信号通道,通常称为A相和B相。当旋转发生时,这两个信号通道的相位关系会发生变化,从而可以计算出旋转方向和旋转的步数。 阅读详情

相关推荐

Verilog的综合指令

Synopsys综合指令

烟花一时的博客 5445

BigDecimal的equals方法做等值比较问题

BigDecimal是java.math包中提供的一种可以用来进行精确运算的类型。在进行金额表示 、金额计算等场景,不能使用double和float等类型,而是使用BigDecimal。 BigDecimal表示数字和进行数字运算之外,代码中还会对BigDecimal进行相等判断。 最新阿里Java开发手册中指出 禁止使用构造方法BigDecimal(double)的方式把double值转化为BigDecimal对象。 说明: BigDecimal(double)存在精度损失风险,在精确计算或值比较的场景中

m0_45226909的博客 5392

edusrc挖掘思路

edusrc挖掘思路前言思路信息搜集系统账号常见漏洞实战分享1、确定目标,语法:site:xxxx.edu.cn2、账号密码组成我们知道了,谷歌语法查找工号3、爆破登录系统4、确定功能,抓具体的url5、添加单引号,报错,是mssql6、报数据库版本,到这一步就可以交了,已经是中危了后记 前言 一月份的时候偶然注意到edusrc,起初是抱着学习的心态去挖几个洞,可是后面发现有证书,而且还贼好看,于是我动了凡心,一顿操作也拿了几本,广西民大、山东理工、同济,未到的有浙大、上海理工,证书要求证书图片可以在我个人

qq_45414878的博客 2万+

BigDecimal判断两值是否相等

  1、用compareTo方法 用compareTo方法来判断BigDecimal两值是否相等,判断结果为0则相等,否则不等,如下: if(amt == null|| amt.compareTo(BigDecimal.ZERO)==0){} 2、不能用== 因为BigDecimal不是基本类型,它只是把你的数值(基本类型)封装到了intCompact(Long类型)这个属性中,是对象类...

xiuxiuzhuanshu的博客 3万+

微机原理-基于8086电压报警2.5V仿真系统设计

*单片机设计介绍,微机原理-基于8086电压报警2.5V仿真系统设计。

2201_75940997的博客 1083

2025.06.24【R语言】|clusterProfiler安装与常见报错FAQ全解

本文介绍了clusterProfiler工具的安装方法及常见报错解决方案。安装可通过Bioconductor或Conda完成,需注意安装配套注释包。文中列举了10种常见报错,包括依赖包缺失、ID类型不匹配、物种不支持等问题,并给出具体解决方法。最后总结了GO/KEGG富集分析的标准流程,包括ID转换、富集分析和可视化步骤,为生物信息学分析提供实用参考。建议使用R≥4.2版本,并确保正确调用BiocManager进行安装。

5994

BigDecimal类型如何比较值相等

BigDecimal是对象,不是基本数据类型,类似于String。所以没有BigDecimal数据类型比较方法这么一说。 这里总结一下用BigDecimal类型对象比较中踩 的坑。 1.BigDecimal不能直接用"=="作比较,编译都不会通过 2.BigDecimal的equals()方法比较不一定对. 这里注意:BigDeciaml的equals()方法,参数Object类型. 可以注意...

没有眉毛的阿斗叶 2万+

LangGraph实战训练营-打造 WhatsApp 全自动消息收发AI智能助手

本文系统梳理了项目架构(WhatsApp Bridge + Talon Host + LangGraph Agent Harness三层设计)、完整环境搭建流程(Docker/本地双模式部署)、核心原理(WhatsApp桥接机制、NVIDIA Parakeet语音转录管线、Cron定时调度、Agent图状状态机),并提供了基础对话、文件操作、语音处理、定时任务等六大实战示例。同时涵盖安全策略、性能优化、数据备份等生产级运维实践,以及十个高频问题的排查方案。

program哲学 191

java学习——BigDecimal的equals原理

那么,无论我们使用new BigDecimal(0.1)还是new BigDecimal(0.10)定义,他的近似值都是0.1000000000000000055511151231257827021181583404541015625这个,那么他的标度就是这个数字的位数,即55。那么他的标度也就是1。但是,他的equals方法使用的时候需要谨慎,因为他在比较的时候,不仅比较两个数字的值,还会比较他们的标度,只要这两个因素有一个是不相等的,那么结果也是false、其他的浮点数也同样的道理。

a25847a的博客 1153

基于STM32设计的数字电子秤

当前项目是采用采用STM32+称重模块+OLED实现了简单的电子秤项目,称重模块上采用24位的ADC芯片,精度较高。实现了称重,校准、去皮等功能。

1万+

海洋CMS admin_notify.php 远程代码执行漏洞复现(CVE-2024-30565)

海洋CMS admin_notify.php 接口处存在远程代码执行漏洞,经过身份验证的远程攻击者可利用该漏洞执行任意代码,写入后门文件,进而控制整个web服务器。

0xSec 2713

BigDecimal的equals方法

BigDecimal作为浮点数据的一个处理对象,在平时用的挺多,但是今天才注意到它的equals方法有特殊的地方。 equals方法是需要比较数值的精度的。 BigDecimal b_1 = new BigDecimal("1");//精度0 BigDecimal b_2 = new BigDecimal("1.0");//精度1 System.out.println(b_1.equals(b_2));//false BigDeci

frwcode的博客 3811

DFT笔记 DC/AC mode与Func

DFT scan可以分为DC和AC两种,区别如下图。

m0_61544122的博客 5723

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

GitHub 17k Star 的Java工程师成神之路,不来了解一下吗! GitHub 17k Star 的Java工程师成神之路,真的不来了解一下吗! GitHub 17k Star 的Java工程师成神之路,真的真的不来了解一下吗! BigDecimal,相信对于很多人来说都不陌生,很多人都知道他的用法,这是一种java.math包中提供的一种可以用来进行精确运算的类型。 很多人都知道,在进行金额表示、金额计算等场景,不能使用double、float等类型,而是要使用对精度支持的更好的BigDecim

HollisChuang's Blog 8948

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

java判断bigdecimal是否为空_为什么阿里巴巴禁止使用BigDecimal的equals方法做等值比较?

BigDecimal,相信对于很多人来说都不陌生,很多人都知道他的用法,这是一种java.math包中提供的一种可以用来进行精确运算的类型。 很多人都知道,在进行金额表示、金额计算等场景,不能使用double、float等类型,而是要使用对精度支持的更好的BigDecimal。 所以,很多支付、电商、金融等业务中,BigDecimal的使用非常频繁。而且不得不说这是一个非常好用的类,其内部自带了很...

weixin_39865102的博客 3万+

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

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

BigDecimal介绍 BigDecimal,相信对于很多人来说都不陌生,很多人都知道他的用法,这是一种java.math包中提供的一种可以用来进行精确运算的类型。 很多人都知道,在进行金额表示、金额计算等场景,不能使用double、float等类型,而是要使用对精度支持的更好的BigDecimal。 所以,很多支付、电商、金融等业务中,BigDecimal的使用非常频繁。而且不得不说这是一个非常好用的类,其内部自带了很多方法,如加,减,乘,除等运算方法都是可以直接调用的。 除了需要用BigDecim

王国隆的技术博客 1105

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

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

BigDecimal,是一种 java.math 包中提供的一种可以用来进行精确运算的类型。 在进行金额表示、金额计算等场景,不能使用 double、float 等类型,而是要使用对精度支持的更好的 BigDecimal。 所以,很多支付、电商、金融等业务中,BigDecimal 的使用非常频繁。而且不得不说这是一个非常好用的类,其内部自带了很多方法,如加,减,乘,除等运算方法都是可以直接调用的。 除了需要用 BigDecimal 表示数字和进行数字运算以外,代码中还经常需要对于数字进行相等判断.

Hello World 652

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

BigDecimal,相信对于很多人来说都不陌生,很多人都知道他的用法,这是一种java.math包中提供的一种可以用来进行精确运算的类型。 很多人都知道,在进行金额表示、金额计算等场景,不能使用double、float等类型,而是要使用对精度支持的更好的BigDecimal。 所以,很多支付、电商、金融等业务中,BigDecimal的使用非常频繁。而且不得不说这是一个非常好用的类,其内部自带了很多方法,如加,减,乘,除等运算方法都是可以直接调用的。 除了需要用BigDecimal表示数字和进行数字运

weixin_43910372的博客 596

阿里为什么不能使用 BigDecimal 的 equals 方法做等值比较?

# 前言 BigDecimal 是 java.math 包中提供的一种可以用来进行精确运算的类型。所以,在支付、电商等业务中,BigDecimal 的使用非常频繁。而且其内部自带了很多方法,如加,减,乘,除等运算方法都是可以直接调用的。 除了需要用 BigDecimal 表示数字和进行数字运算以外,代码中还经常需要对于数字进行相等判断。 说到等值比较,咱们先看看《阿里巴巴Java开发手册》中的要求: 那么为什么会有这样的要求呢~ 其中的奥秘是什么呢~ 请各位小伙伴听我娓娓道来…

欢迎来到我的博客 282

bigdecimal判断是否为null_为什么阿里巴巴禁止使用BigDecimal的equals方法做等值比较?...

BigDecimal,相信对于很多人来说都不陌生,很多人都知道他的用法,这是一种java.math包中提供的一种可以用来进行精确运算的类型。很多人都知道,在进行金额表示、金额计算等场景,不能使用double、float等类型,而是要使用对精度支持的更好的BigDecimal。所以,很多支付、电商、金融等业务中,BigDecimal的使用非常频繁。而且不得不说这是一个非常好用的类,其内部自带了很多方...

weixin_39679468的博客 1145

bigdecimal 等于0_为什么阿里巴巴禁止使用BigDecimal的equals方法做等值比较?

前言BigDecimal,相信对于很多人来说都不陌生,很多人都知道他的用法,这是一种java.math包中提供的一种可以用来进行精确运算的类型。很多人都知道,在进行金额表示、金额计算等场景,不能使用double、float等类型,而是要使用对精度支持的更好的BigDecimal。所以,很多支付、电商、金融等业务中,BigDecimal的使用非常频繁。而且不得不说这是一个非常好用的类,其内部自带了很...

weixin_39534321的博客 180
上一篇: 【Java面试进阶】谈谈为什么禁止使用Executors创建线程池?
下一篇: 【面试题】Java常见面试题集锦
镰刀韭菜
博客等级 码龄12年 2万+粉丝 853原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

镰刀韭菜

看在我不断努力的份上,支持我吧

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值