血的教训,BigDecimal踩过的坑

news2024/12/23 19:12:35

很多人都用过Java的BigDecimal类型,但是很多人都用错了。如果使用不当,可能会造成非常致命的线上问题,因为这涉及到金额等数据的计算精度。

首先说一下,一般对于不需要特别高精度的计算,我们使用double或float类型就可以了。

由于计算机天生的无法表达完整的二进制浮点数的小数,二进制的小数是无限循环的,所以只能无限接近于精确值,这就造成了浮点计算的精度问题。此时就需要使用BigDecimal类型了。

踩坑一:初始化

关于浮点数精度的问题,我们可以看下这个代码。

打印结果会是0.2吗?不是,打印结果是0.19999999。因为b最大化接近于0.8,可能是0.80000001,近似于0.8。这就是为什么说精度要求不高时可以用double或float类型,一旦涉及到金额就不能使用浮点类型的原因。

知道了这个原理,我们使用BigDecimal能否避免浮点计算的精度问题?看下这个代码。

打印结果如下:

使用BigDecimal构造函数和使用valueOf方法初始化,两种方式得到的结果不一样,valueOf方法初始化的BigDecimal数据计算是精确的。我们看下源码就能明白了。

valueOf方法会把浮点数先转换成字符串,再用BigDecimal构造函数初始化。所以就不存在精度问题了。当然,这里要特别注意的是,valueOf方法对double类型的值可以保证精度,但是如果传的是float类型,例如0.8f,则依然会有精度问题。

踩坑结论:

  • 使用BigDecimal构造函数时,传字符串而不要传浮点类型。
  • 尽量使用valueOf方法初始化,并且不要传float类型数据。

踩坑二:比较大小

两个BigDecimal值比较是否相等,是使用equals方法还是使用compareTo方法?先来看个例子。

打印结果:

equals判断a和b不相等,compareTo判断a和b相等。我们看下equals的源码。

equals除了比较值的大小,还会比较值的精度。

踩坑结论:

  • 比较两个BigDecimal值的大小,使用compareTo方法。
  • 比较大小且限制精度,使用equals方法。

踩坑三:除法设置精度

在进行BigDecimal计算特别是除法计算时,很多人会忘记设置精度和舍入模式,最终结果就是程序会报一个ArithmeticException异常。先看示例。

报错信息如下图

官方文档是这样解释的:

"If the quotient has a nonterminating decimal expansion and the operation is specified to return an exact result, an ArithmeticException is thrown. Otherwise, the exact result of the division is returned, as done for other operations."

翻译过来的意思是:

"如果商具有非终止的十进制展开,并且指定运算返回精确的结果,则引发ArithmeticException。否则,将返回除法的确切结果,就像对其他操作所做的那样。"

用人话解释上述文字,意思就是如果divide方法计算得到的商是一个无限小数,而代码预期得到一个精确数字,那么就会抛出ArithmeticException异常。

正确的使用divide代码如下。

打印结果:

设置了c的精度为2,RoundingMode.HALF_UP是向上舍入模式,即四舍五入。

踩坑结论:使用BigDecimal进行计算时,结果一定要设置精度和舍入模式。

踩坑四:字符串转换

想将BigDecimal类型转成字符串,用toString方法?先来看个示例。

打印结果:

可以看出,toString方法将BigDecimal的值转成了科学计数法的值。如果想要转成正常的数值应该使用什么方法呢?我们可以先看下BigDecimal三种转字符串的方法。

  • toString():如果需要指数,则使用科学计数法。
  • toPlainString():不带指数的字符串表现形式。
  • toEngineeringString():如果需要指数,则使用工程计数法。

踩坑结论:结合具体业务选择适用的字符串转换方法。

最后,关于数值格式化的功能,我们可以利用NumberFormat类,对BigDecimal进行格式化控制。代码示例如下。

打印结果:

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

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

相关文章

微服务黑马头条(简略笔记)

Linux中nacos的拉取安装 拉取naocs镜像:docker pull nacos/nacos-server:1.2.0创建容器:docker run --env MODEstandalone --name nacos --restartalways -d -p 8848:8848 nacos/nacos-server:1.2.0访问地址:http://192.168.200.130:8848/n…

Python常见面试知识总结(一):迭代器、拷贝、线程及底层结构

前言: Hello大家好,我是Dream。 今天来总结一下Python和C语言中常见的面试知识,欢迎大家一起前来探讨学习~ 【一】Python中迭代器的概念? 可迭代对象是迭代器、生成器和装饰器的基础。简单来说,可以使用for来循环遍历…

vue自定义指令及常用的自定义指令封装

vue2 自定义指令 官网链接https://v2.cn.vuejs.org/v2/guide/custom-directive.html 指令注册 这里是一个 Vue2 的指令合集,详细的指令移步下面具体的指令文章,现在我们在这里要介绍如何在项目中统一管理和使用这些指令。 注册指令 单文件引入注册 …

Linux上进行Nacos安装

Nacos安装指南 仅供参考,若有错误,欢迎批评指正! 后期会继续上传docker安装nacos的过程! 1.Windows安装 开发阶段采用单机安装即可。 1.1.下载安装包 在Nacos的GitHub页面,提供有下载链接,可以下载编译好…

性能测试基础

性能测试分类 客户端性能:测试APP自身的性能,例如CPU、内存消耗;web页面元素渲染速度 服务端性能:测试服务端项目程序的支持的并发、处理能力、响应时间等,主要通过接口来做性能测试 性能测试指标 并发 同时向服务…

企业举办年会,可以邀请哪些媒体进行宣传?

传媒如春雨,润物细无声,大家好,我是51媒体网胡老师。 年关将至,筹办年会成为每个企业必做的事情,也是大家非常期待的年终大会,在我们策划年会时候,也要抓住最后宣传的机会。那么企业举办年会时…

【信息安全】-ISO/IEC 27001-2022(翻译)

文章目录 范围规范性引用文件3 术语和定义4 组织环境(P)4.1 理解组织及其环境4.2 理解相关方的需求和期望组织应确定:a) 信息安全管理体系相关方;b) 这些相关方的相关要求;c) 哪些要求可以通过信息安全管理体系得到解决。注:相关方的要求可包括法律、法规…

MyBatisPlus简介

1 简介 MyBatis-Plus(简称 MP)是一个 MyBatis的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。 2、特性 无侵入 只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑…

《IT圈里的“鄙视链”:看不起谁又被谁看不起?》

文章目录 每日一句正能量前言一、编程语言篇二、工具篇三、操作系统篇四、硬件篇五、职场篇后记 每日一句正能量 人的结构就是相互支撑,众人的事业需要每个人的参与。 前言 每个领域都存在着错综复杂的鄙视链,这一点在IT 领域更为突出。从编程语言、工具&#xff0…

SD生成的图像不清晰,如何解决

文生图 选择高清修复: 几点注意 重绘幅度:这里不用太高,他会根据你生成的低分辨率图像,生成高分辨率的图像,可以选择0.3~05之间,给AI跟多想象力空间可以选择0.5 ~ 0.7。太低边缘模糊,太高了可能…

Layui深入

1、代码&#xff1a; <!DOCTYPE html> <html> <head> <meta charset"utf-8"> <title>注册页面</title> <style> .container { max-width: 600px; margin: 0 auto; padding: 20px; …

14-Kafka-Day02

第 4 章 Kafka Broker 4.1 Kafka Broker 工作流程 4.1.1 Zookeeper 存储的 Kafka 信息 &#xff08;1&#xff09;启动 Zookeeper 客户端。 bin/zkCli.sh 因为你在配置kafka的时候指定了它的名字。 &#xff08;2&#xff09;通过 ls 命令可以查看 kafka 相关信息。 [zk: …

InsCode实践分享:如何实现自动化代码审查和质量控制?

文章目录 文章目录 概要 整体架构流程 InsCode的解释 技术展示 小结 概要 InsCode是一款面向中小型企业的代码审查和自动化质量控制工具。本文将分享如何使用InsCode来实现自动化代码审查和质量控制&#xff0c;帮助企业在代码开发和维护过程中降低风险&#xff0c;提高效率和…

Java最全面试题专题---2、Java集合容器(1)

集合容器概述 什么是集合 **集合框架&#xff1a;**用于存储数据的容器。 集合框架是为表示和操作集合而规定的一种统一的标准的体系结构。 任何集合框架都包含三大块内容&#xff1a;对外的接口、接口的实现和对集合运算的算法。 **接口&#xff1a;**表示集合的抽象数据类…

基于springboot实现的人力资源管理系统

一、系统架构 前端&#xff1a;html | js | css | jquery | bootstrap 后端&#xff1a;springboot | mybatis 环境&#xff1a;jdk1.7 | mysql | maven 二、代码及数据库 三、功能介绍 01. 登录页 02. 首页 03. 员工管理 04. 奖惩管理 05. 合同管理 06. 薪酬管理 07.…

Python从入门到精通五:Python函数

函数介绍 学习目标&#xff1a; 快速体验函数的使用了解函数的作用 函数&#xff1a;是组织好的&#xff0c;可重复使用的&#xff0c;用来实现特定功能的代码段。 我们使用过的&#xff1a;input()、print()、str()、int()等都是Python的内置函数。 为什么要学习、使用函…

WPS没保存关闭了怎么恢复数据?3个方法,完成数据恢复!

“我今天在使用WPS时&#xff0c;突然有点急事出去了一趟&#xff0c;但是我忘记保存文档了&#xff0c;回来之后发现电脑自动关机了&#xff0c;我的文档也没了&#xff01;这可怎么办呢&#xff1f;有什么办法可以找回这些数据吗&#xff1f;” 在快节奏的工作中&#xff0c;…

软件科技成果鉴定测试有什么好处?注意事项有哪些?

软件科技成果鉴定测试是指对软件科技成果进行检测和评估的过程。通过这个测试&#xff0c;可以评估软件科技成果的技术水平、功能性能以及可靠性&#xff0c;并为相关单位和个人提供科学的评价依据。    一、进行软件科技成果鉴定测试有以下好处&#xff1a;   1、客观评价…

专业的内外网文件摆渡系统,如何帮助企业提升协作效率?

伴随着全球数字化转型的持续深入&#xff0c;数字经济的蓬勃发展&#xff0c;数据资产已成为非常重要的生产要素。近年来&#xff0c;全球数据泄密事件频发&#xff0c;数据泄密事件的平均成本逐年攀升。考虑到业务安全需要&#xff0c;绝大多数企业会考虑网络隔离&#xff0c;…

功能有更新 | Bonree ONE 权限版本新增环境、资源域、角色概念

近期&#xff0c;博睿数据根据一体化智能可观测平台 Bonree ONE 产品本身&#xff0c;以及用户反馈进行持续的更新和优化。继第01期 RUM 增强 APP 端快照配置全量会话回放与自定义协议网络请求采集功能之后&#xff0c;以下为 Bonree ONE 产品功能更新报告第02期内容&#xff0…