谁再用Double定义存储计算金额,我劈了他

news2024/9/22 15:31:24

在这里插入图片描述

不是三婶儿偏执,非要吐槽。家人们,咱就是说,按照基操逻辑谁会把严格金额计算相关的数据使用double类型呢…
“我以为吕布已经够勇猛了,这是谁的部下?”

前几天,一同事让帮忙写段代码。内容比较常规,就是按照自定义规则自动计算出一些金额数据。楼主想着暂时也不忙,就帮着写写呗。好家伙!不写不知道,当看到他用Double类型定义存储金额时,内心瞬间沸腾了。嗯,真是个小(大)可(傻)爱(逼)…

在这里插入图片描述

咱就是说,金额相关计算第一考虑肯定是确保精准,优选BigDecimal类型呀,Double类型很容易丢失精度的。尤其是金额,一定要严谨!

你看chatgpt都知道优先使用BigDecimal。

在这里插入图片描述

果不其然,这…真是暴风雨的前奏。我发现有好几个业务模块都使用了这些金额数据做运算,多次加减乘除之类的…

好家伙,“海燕啊,你可长点心吧!”。

在这里插入图片描述

那下面楼主就来详细分析一下,为什么更加建议使用BigDecimal。开整!

文章目录

  • 一、BigDecimal类型数据和Double类型
    • 1.1、BigDecimal
    • 1.2、Double和double的区别
      • 1.2.1、double
      • 1.2.2、Double
      • 1.2.3、double和Double之间的关系
  • 二、两种类型数据的适用场景、优缺点
    • 2.1、Double类型
    • 2.2、BigDecimal类型
  • 三、为什么不建议用Double类型计算金额
    • 3.1、Double类型计算精度易丢失
    • 3.2、数值过大会变为科学记数法形式
  • 四、BigDecimal常用方法
    • 4.1、BigDecimal的初始化
    • 4.2、BigDecimal加法
    • 4.3、BigDecimal减法
    • 4.4、BigDecimal乘法
    • 4.5、BigDecimal除法
    • 4.6、BigDecimal比较大小
    • 4.7、BigDecimal工具类

一、BigDecimal类型数据和Double类型

首先,先来了解一下什么是BigDecimal、什么是Double、什么是double。以及Double和double之间有什么关系。

嗯,是有关系,但也不是情侣关系…

在这里插入图片描述

1.1、BigDecimal

对于什么是BigDecimal,百度百科中这样描述:

Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算。双精度浮点型变量double可以处理16位有效数。在实际应用中,需要对更大或者更小的数进行运算和处理。float和double只能用来做科学计算或者是工程计算,在商业计算中要用java.math.BigDecimal。BigDecimal所创建的是对象,我们不能使用传统的+、-、*、/等算术运算符直接对其对象进行数学运算,而必须调用其相对应的方法。方法中的参数也必须是BigDecimal的对象。构造器是类的特殊方法,专门用来创建对象,特别是带有参数的对象。

主要是: 可对超过16位有效位的数进行精确的运算。

1.2、Double和double的区别

1.2.1、double

八大基本数据类型之一,双精度浮点数。

double(双精度浮点型)是计算机使用的一种资料型别。比起单精度浮点数(float),double(双精度浮点数)使用 64 位(8字节) 来储存一个浮点数。 它可以表示十进制的15或16位有效数字,负值取值范围为 -1.7976E+308 到 -4.94065645841246544E-324,正值取值范围为 4.94065645841246544E-324 到 1.797693E+308

1.2.2、Double

Double是基于基本数据类型double的一个封装类,就是我们常用的java.lang.Double。

在这里插入图片描述

1.2.3、double和Double之间的关系

从jdk1.5开始,引入了“自动装箱”、“自动拆箱”的概念,简化了基本数据类型和包装类之间的转化,提高了使用效率。

关于什么是装箱、拆箱。举个栗子:比如我们常用的List就是一个自动装箱、拆箱的体现。

在这里插入图片描述

如图所示,楼主定义了一个Integer类型的list。当往list中放入数据1和2时,会把int类型自动转换为Integer类型,这个过程就是自动装箱。

在这里插入图片描述

反过来说,当从list中取出数据时,会把Integer类型自动转换为int类型,这个过程就是自动拆箱。

自动装箱最大的优点就是:可以直接使用包装类中所有的方法。

我们直接调用即可,方法内部都已经帮我们处理好了。感兴趣的可以看下源码深入了解哈,这里不再过多介绍。
在这里插入图片描述

二、两种类型数据的适用场景、优缺点

2.1、Double类型

适用场景:双精度、非重要性、或“相对模糊”的数据存储。比如:百分比计算。

缺点:数值容易丢失精度。

优点:执行效率高。

2.2、BigDecimal类型

适用场景:较为严谨的数值计算。比如:交易金额相关计算。

优点:数值计算较为精准。

缺点:较Double类型执行效率弱一些。

三、为什么不建议用Double类型计算金额

3.1、Double类型计算精度易丢失

当我们进行数值加减乘除运算时,Double类型很大程度上会产生误差。

如下图示例,楼主定义了2个Double类型数据的加减乘除,运算结果有3个产生了误差。有误差,但是误差不大。

在这里插入图片描述

那么为什么会存在这个问题呢?

可想而知,double类型在运算时,会先将数值转换成二进制然后再做运算。但是在转换过程中,可能会发生存储小数部分的位数不够的现象(无限循环小数),所以很大程度上可能会有非常小的误差产生

因此,不要直接使用入参double类型数值直接进行运算。可考虑使用string类型参数进行处理。

在这里插入图片描述

3.2、数值过大会变为科学记数法形式

当数值过大时,会变为这种科学记数法形式。

在这里插入图片描述
解决方案:可考虑使用BigDecimal类型进行转换。

四、BigDecimal常用方法

4.1、BigDecimal的初始化

楼主分别定义了2个不同类型的入参。

在这里插入图片描述

眼尖的小伙伴估计注意到了,实例化a对象时new BigDecimal(“0.12”)传入的是字符串,实例化b对象时new BigDecimal(0.12)传入的是double数值。大家觉得运行结果会一样吗?

如果你认为一样,那就错了。

在这里插入图片描述

字符串类型的输出了“0.12”,而double数值类型的却输出了“0.11999999999999999555910790149937383830547332763671875”。

在这里插入图片描述

这又回归到了上面说所的二进制转换存储小数部分的位数不够,造成的误差。使用double类型初始化BigDecimal对象,进行运算时可能会出现精度不准确的问题。

在这里插入图片描述

所以一定注意:不要使用double类型作为入参,直接去new一个BigDecimal对象!可能会有精度误差!

那么,为什么string就可以呢?

string是不可变的,定义为string之后再转换为数值肯定是固定的啊。

底层很多实现也是这个原理。比如BigDecimal.valueOf()方法,如果输入的是double类型,实质上源码中还是先转化为了字符串。

在这里插入图片描述

对于整型或保留小数位的,也有相应的处理方法。

在这里插入图片描述

方法有很多,大家想了解的可自行研究下,楼主就不再一一示例啦。

在这里插入图片描述

4.2、BigDecimal加法

BigDecimal add(BigDecimal augend)

在这里插入图片描述

两个BigDecimal类型数据相加,方法调用、及运行效果。

在这里插入图片描述

4.3、BigDecimal减法

BigDecimal subtract(BigDecimal subtrahend)

在这里插入图片描述
两个BigDecimal类型数据相减,方法调用、及运行效果。

在这里插入图片描述

4.4、BigDecimal乘法

BigDecimal multiply(BigDecimal multiplicand)

在这里插入图片描述

两个BigDecimal类型数据相乘,方法调用、及运行效果。

在这里插入图片描述

4.5、BigDecimal除法

BigDecimal divide(BigDecimal divisor)

在这里插入图片描述

两个BigDecimal类型数据相除,方法调用、及运行效果。

在这里插入图片描述

哎呦,惊喜不惊喜,意外不意外?相除的时候出现了无限循环小数

因此 相除的场景下尽可能设置保留小数位,可避免运算当中抛出异常

在这里插入图片描述

4.6、BigDecimal比较大小

楼主分别定义了2个值为“0.12”的数据a、b,以及值为“0.120”的数据c进行比较。

在这里插入图片描述

可以发现:相同值“0.12”通过双等号对比返回的结果是false,equals对比返回的是true。而“0.12”和“0.120”实质上数值大小是一样的,但通过双等号或equals进行对比,返回均为false

那么,对于BigDecimal类型如何比较大小呢?(叫我靓妹我就告诉你…)

在这里插入图片描述

方法就是:使用compareTo方法进行比较

在这里插入图片描述

a、b两值进行比较:a.compareTo(b) 。 结果为0表示a、b值相等。结果为-1表示a小于b。结果为1表示a大于b

4.7、BigDecimal工具类

为大家附上常用的操作工具类,直接调用即可。


package com.wss.demo.cas;

import java.math.BigDecimal;

public class ArithUtil {


    private static final int DEF_DIV_SCALE = 2; // 小数点后的保留位数

    /**
     * Double精确的加法运算
     *
     * @param d1 被加数
     * @param d2 加数
     * @return 两个参数的和
     */
    public static BigDecimal add(double d1, double d2) {
        BigDecimal value1 = new BigDecimal(Double.toString(d1));
        BigDecimal value2 = new BigDecimal(Double.toString(d2));
        return value1.add(value2);
    }

    /**
     * Double精确的减法运算
     *
     * @param d1 被减数
     * @param d2 减数
     * @return 两个参数的差
     */
    public static BigDecimal sub(double d1, double d2) {
        BigDecimal value1 = new BigDecimal(Double.toString(d1));
        BigDecimal value2 = new BigDecimal(Double.toString(d2));
        return value1.subtract(value2);
    }

    /**
     * Double精确的乘法运算
     *
     * @param d1 被乘数
     * @param d2 乘数
     * @return 两个参数的积
     */
    public static BigDecimal mul(double d1, double d2) {
        BigDecimal value1 = new BigDecimal(Double.toString(d1));
        BigDecimal value2 = new BigDecimal(Double.toString(d2));
        return value1.multiply(value2);
    }

    /**
     * Double精确的除法运算, 当出现除不尽的情况时, 精确到小数点以后n位, 以后的数字四舍五入
     *
     * @param d1 被除数
     * @param d2 除数
     * @return 两个参数的商
     */
    public static BigDecimal div(double d1, double d2) {
        return div(d1, d2, DEF_DIV_SCALE);
    }

    /**
     * Double精确的除法运算, 当出现除不尽的情况时, 精确到小数点以后n位, 以后的数字四舍五入
     *
     * @param d1    被除数
     * @param d2    除数
     * @param scale 表示需要精确到小数点的后几位
     * @return 两个参数的商
     */
    public static BigDecimal div(double d1, double d2, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException("参数[scale]必须是正整数或者零");
        }
        BigDecimal value1 = new BigDecimal(Double.toString(d1));
        BigDecimal value2 = new BigDecimal(Double.toString(d2));
        return value1.divide(value2, scale, BigDecimal.ROUND_HALF_UP);
    }

    /**
     * 比较大小
     */
    public static boolean equalTo(BigDecimal b1, BigDecimal b2) {
        if(b1 == null || b2 == null) {
            return false;
        }
        return 0 == b1.compareTo(b2);
    }

}

嗯,今天的总结就先到这吧。散会了,别忘记给三婶儿点个赞哈~

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/357407.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Unity之ASE实现边缘光效果

一.前言 今天来实现一个简单的边缘光效果&#xff0c;可以应用与物体表面的一种荧光外溢的效果&#xff0c;特别是用在人的身体表面&#xff0c;会让人的皮肤更细腻&#xff0c;更好看。 物体上效果如下: 人体表面效果如下&#xff1a; 我们可以看到&#xff0c;这种人体表面…

Redis的整合和使用

引入依赖 <!--整合redis--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency>添加配置 spring.redis.host127.0.0.1 spring.redis.port6379 spring.…

算法训练营 day49 动态规划 爬楼梯 (进阶)零钱兑换 完全平方数

算法训练营 day49 动态规划 爬楼梯 &#xff08;进阶&#xff09;零钱兑换 完全平方数 爬楼梯 &#xff08;进阶&#xff09; 70. 爬楼梯 - 力扣&#xff08;LeetCode&#xff09; 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同…

PPO(proximal policy optimization)算法

博客写到一半发现有篇讲的很清楚&#xff0c;直接化缘了 https://www.jianshu.com/p/9f113adc0c50 Policy gradient 强化学习的目标&#xff1a;学习到一个策略πθ(a∣s)\pi\theta(a|s)πθ(a∣s)来最大化期望回报。 一种直接的方法就是在策略空间中直接搜索来得到最优策略&…

详解Ansible中角色的使用

目录 一、ansible roles 1、ansible 角色简介 2、roles目录结构 3、role存放的路径在配置文件ansible.cfg中定义 4、创建目录结构 二、roles的写法及应用 1、覆盖变量 2、控制任务执行顺序 三、ansible—galaxy命令工具 一、ansible roles 1、ansible 角色简介 * Ans…

VNCTF 2023复现

文章目录象棋王子电子木鱼BabyGo象棋王子 签到题&#xff0c;直接在源码中找就ok。 找到一处编码&#xff0c;在控制台输出。 flag为&#xff1a;flag{w3lc0m3_t0_VNCTF_2023~~~} 电子木鱼 需要先理清代码逻辑。 存在三个路由。 一&#xff1a;/路由用来查看当前的功德数量…

兼职任务平台收集(二)分享给有需要的朋友们

互联网时代&#xff0c;给人们带来了很大的便利。信息交流、生活缴费、足不出户购物、便捷出行、线上医疗、线上教育等等很多。可以说&#xff0c;网络的时代会一直存在着。很多人也在互联网上赚到了第一桶金&#xff0c;这跟他们的努力和付出是息息相关的。所谓一份耕耘&#…

Git详解

Git1.Git简介1.1 Git是什么1.2 Git的作用1.3 Git的简介1.4 Git的下载和安装1.5 Git的安装目录结构如下2.Git代码托管服务2.1 常用的Git代码托管服务1.Git简介 1.1 Git是什么 Git是一个分布式版本控制工具&#xff0c;主要用于管理开发过程中的源代码文件&#xff08;Java类、x…

java 基于maven多模块合并打包部署

项目环境 jdk 1.8spring 2.7.xmaven 3.6 项目结构 模块功能 client – 对外service common – 共用工具切面等 main – 启动类 goods – 子模块具体实现 模块间依赖关系 client – 无依赖 common – 无依赖 main – client、common、goods goods – client、common 具体P…

[软件工程导论(第六版)]第6章 详细设计(课后习题详解)

文章目录1 假设只有SEQUENCE和DO-WHILE两种控制结构&#xff0c;怎样利用它们完成 IF THEN ELSE操作&#xff1f;2 假设只允许使用SEQUENCE和IF-THEN-ELSE两种控制结构&#xff0c;怎样利用它们完成DO WHILE操作&#xff1f;3 画出下列伪码程序的程序流程图和盒图&#xff1a;4…

C/C++每日一练(20230219)

目录 1. 用队列实现栈 2. 判断是否能组成三角形 3. 只出现一次的数字 II 附录 栈&#xff08;Stack&#xff09;和队列&#xff08;Queue&#xff09;的异同 1. 栈和队列的相同点 2. 栈和队列的不同点 1. 用队列实现栈 请你仅使用两个队列实现一个后入先出&#xff08;…

基于FFmpeg和Screen Capturer Recorder实现屏幕和声音的录制

当我们看到一些精彩的视频画面&#xff0c;但无法下载时&#xff0c;可以通过录屏的方式将视频和音频录制下来。 这个时候我们需要安装采集视频和音频的工具screen-capture-recorder。 以下是在windows10环境下&#xff0c;基于FFmpeg和Screen Capturer Recorder实现屏幕和声音…

带噪学习-概述

在实际应用的时候&#xff0c;我们的样本不会是完全干净的&#xff0c;即存在噪声样本。那使用存在噪声的样本时&#xff0c;我们如何更有效的进行模型学习呢&#xff1f;Label Dependent Nose样本选择&#xff08;Sample Selection&#xff09;第一种很直接的想法&#xff0c;…

PDDON在线画图是如何惊艳到你的?

1. 简介 PDDON是一款支持低代码(lowcode)的免费在线画图工具。可用于绘制架构图、流程图、UML、网络拓扑图、韦恩图、鱼骨图、思维导图、BPMN等&#xff0c;并且支持对象建模、数据库建模、代码/脚本生成。 PDDON与市面上现有的画图工具对比有哪些优势呢&#xff1f; 完全免费…

SpringJDBC的框架

JDBC框架概述目录概述需求&#xff1a;设计思路实现思路分析1.Spring 编程式事务管理2.方法&#xff1a;3.Marks4.网页解析器5.步骤src性能参数测试&#xff1a;参考资料和推荐阅读Survive by day and develop by night. talk for import biz , show your perfect code,full bu…

【pytorch】nn.SmoothL1Loss 函数使用

SmoothL1 Loss1、Smooth L1 Loss2、nn.SmoothL1Loss 函数使用1、Smooth L1 Loss 本方法由微软rgb大神提出&#xff0c;Fast RCNN论文提出该方法 1&#xff09;假设x为预测框和真实框之间的数值差异&#xff0c;常用的 L1 loss、L2 Loss 和 smooth L1 loss 定义分别为&#xf…

浅谈Spring中事务管理器

由于事务部分代码在设计上整体比较简单&#xff0c;我自己觉得它在设计上没有什么特别让我眼前一亮的东西&#xff0c;所以下文更多的是侧重执行流程&#xff0c;能理解事务管理器等一众概念以及相关的变量含义&#xff0c;真正遇到Bug会调试&#xff0c;知道在什么地方打断点就…

前端FileReader对象实现图片file文件转base64

1、file转base64具体代码 // 图片file转base64方法&#xff08;file文件&#xff0c;回调函数&#xff09;fileToBase64(file, callback) {// 创建FileReader对象&#xff08;不兼容IE&#xff09;let reader new FileReader();// 将file转为base64 &#xff08;异步操作&…

如何正确选择好用的投票平台微信公众平台投票链接链接投票平台

“年度人物楷模”网络评选投票_免费链接投票_作品投票通道_扫码投票怎样进行现在来说&#xff0c;公司、企业、学校更多的想借助短视频推广自己。通过微信投票小程序&#xff0c;网友们就可以通过手机拍视频上传视频参加活动&#xff0c;而短视频微信投票评选活动既可以给用户发…

driver.js web 新手交互引导工具库

前言 最近逛技术论坛发现了 driver.js 这个库&#xff0c;相信很多人在app中都碰到过功能引导的&#xff0c;这个库就可以用来做这个功能。web段项目很少见到功能引导的&#xff0c;但是用在uniapp 、浏览器插件 中感觉还是十分不错的&#xff0c;因此打算来简单学习一下&…