BigDecimal 详解
阿里巴巴 Java 开发手册》中提到:“为了避免精度丢失,可以使用 BigDecimal
来进行浮点数的运算”。
浮点数的运算竟然还会有精度丢失的风险吗?确实会!
示例代码:
float a = 2.0f - 1.9f;
float b = 1.8f - 1.7f;
System.out.println(a);// 0.100000024
System.out.println(b);// 0.099999905
System.out.println(a == b);// false
为什么浮点数 float
或 double
运算的时候会有精度丢失的风险呢?
这个和计算机保存浮点数的机制有很大关系。我们知道计算机是二进制的,而且计算机在表示一个数字时,宽度是有限的,无限循环的小数存储在计算机时,只能被截断,所以就会导致小数精度发生损失的情况。这也就是解释了为什么浮点数没有办法用二进制精确表示。
就比如说十进制下的 0.2 就没办法精确转换成二进制小数:
// 0.2 转换为二进制数的过程为,不断乘以 2,直到不存在小数为止, // 在这个计算过程中,得到的整数部分从上到下排列就是二进制的结果。 0.2 * 2 = 0.4 -> 0 0.4 * 2 = 0.8 -> 0 0.8 * 2 = 1.6 -> 1 0.6 * 2 = 1.2 -> 1 0.2 * 2 = 0.4 -> 0(发生循环) ...
关于浮点数的更多内容,建议看一下计算机系统基础(四)浮点数这篇文章。
BigDecimal 介绍
- 定义
BigDecimal
是 Java 中的一个类,用于高精度的十进制算术运算。在处理货币、科学计算等对精度要求极高的场景中非常有用。与基本数据类型(如float
和double
)不同,BigDecimal
可以精确地表示和计算浮点数,避免了浮点数在计算机中存储和运算时可能产生的精度损失问题。
- 构造方法
- 可以通过多种方式构造
BigDecimal
对象。例如:- 使用字符串作为参数:
BigDecimal bd = new BigDecimal("123.45");
。这种方式是推荐的,因为它可以准确地表示数字的值。如果使用double
或float
值来构造BigDecimal
,可能会引入不精确的值,因为double
和float
本身在存储上存在精度问题。 - 也可以使用整数作为参数来构造,如
BigDecimal bd2 = new BigDecimal(123);
,这样会创建一个表示整数值的BigDecimal
对象。
- 使用字符串作为参数:
- 可以通过多种方式构造
- 主要方法
- 加法运算
- 使用
add
方法实现加法。例如:BigDecimal num1 = new BigDecimal("10.5");
BigDecimal num2 = new BigDecimal("5.5");
BigDecimal sum = num1.add(num2);
// 结果为16.0
- 使用
- 减法运算
- 通过
subtract
方法进行减法。例如:BigDecimal num3 = new BigDecimal("20.0");
BigDecimal num4 = new BigDecimal("3.0");
BigDecimal difference = num3.subtract(num4);
// 结果为17.0
- 通过
- 乘法运算
- 利用
multiply
方法进行乘法。例如:BigDecimal num5 = new BigDecimal("4.0");
BigDecimal num6 = new BigDecimal("3.0");
BigDecimal product = num5.multiply(num6);
// 结果为12.0
- 利用
- 除法运算
- 使用
divide
方法进行除法。需要注意的是,除法可能会出现除不尽的情况,所以可能需要指定舍入模式。例如:BigDecimal num7 = new BigDecimal("7.0");
BigDecimal num8 = new BigDecimal("3.0");
BigDecimal quotient = num7.divide(num8, 2, RoundingMode.HALF_UP);
。这里指定了保留两位小数并且采用四舍五入的舍入模式,结果为2.33
。
- 使用
- 加法运算
- 舍入模式(RoundingMode)
BigDecimal
提供了多种舍入模式,这些模式在进行除法等可能产生不精确结果的运算时非常重要。- ROUND_UP:总是在非零舍弃部分的左边数字上加 1。例如,将
1.23
舍入到整数位,结果为2
。 - ROUND_DOWN:总是直接舍弃非零舍弃部分。例如,将
1.99
舍入到整数位,结果为1
。 - ROUND_CEILING:如果是正数,行为和
ROUND_UP
一样;如果是负数,行为和ROUND_DOWN
一样。 - ROUND_FLOOR:如果是正数,行为和
ROUND_DOWN
一样;如果是负数,行为和ROUND_UP
一样。 - ROUND_HALF_UP:这是最常见的四舍五入模式。如果舍弃部分大于等于 0.5,则在左边数字上加 1;否则直接舍弃。例如,将
1.5
舍入到整数位,结果为2
;将1.4
舍入到整数位,结果为1
。 - ROUND_HALF_DOWN:如果舍弃部分大于 0.5,则在左边数字上加 1;否则直接舍弃。与
ROUND_HALF_UP
的区别在于,当舍弃部分正好是 0.5 时,ROUND_HALF_DOWN
是直接舍弃,而ROUND_HALF_UP
是进位。例如,将1.5
舍入到整数位,结果为1
。
- 比较操作
- 可以使用
compareTo
方法来比较两个BigDecimal
对象的大小。 - 例如:
BigDecimal num9 = new BigDecimal("5.0");
BigDecimal num10 = new BigDecimal("3.0");
int result = num9.compareTo(num10);
。如果num9
大于num10
,result
的值为1
;如果num9
等于num10
,result
的值为0
;如果num9
小于num10
,result
的值为- 1
。
- 可以使用
- 应用场景
- 金融领域:在处理货币金额计算时,由于货币的精度要求很高,不能有丝毫的误差。例如银行账户的余额计算、交易金额计算等。
- 科学计算:在一些对精度要求极高的科学计算场景中,如物理实验数据处理、高精度的数学模型计算等,
BigDecimal
能够提供准确的计算结果。
BigDecimal 常见方法:
创建
我们在使用 BigDecimal
时,为了防止精度丢失,推荐使用它的BigDecimal(String val)
构造方法或者 BigDecimal.valueOf(double val)
静态方法来创建对象。
《阿里巴巴 Java 开发手册》对这部分内容也有提到,如下图所示。
大小比较:
a.compareTo(b)
: 返回 -1 表示 a
小于 b
,0 表示 a
等于 b
, 1 表示 a
大于 b
。
BigDecimal a = new BigDecimal("1.0");
BigDecimal b = new BigDecimal("0.9");
System.out.println(a.compareTo(b));// 1
通过 setScale
方法设置保留几位小数以及保留规则。保留规则有挺多种,不需要记,IDEA 会提示。
BigDecimal m = new BigDecimal("1.255433");
BigDecimal n = m.setScale(3,RoundingMode.HALF_DOWN);
System.out.println(n);// 1.255
相关文章:

BigDecimal 详解
阿里巴巴 Java 开发手册》中提到:“为了避免精度丢失,可以使用 BigDecimal 来进行浮点数的运算”。 浮点数的运算竟然还会有精度丢失的风险吗?确实会! 示例代码: float a 2.0f - 1.9f; float b 1.8f - 1.7f; Syst…...

ESP-HaloPanel:用 ESP32-C2 打造超低成本智能家居面板
项目简介 在生活品质日益提升的今天,智能家居系统已经走进了千家万户,并逐渐成为现代生活的一部份。与此同时,一款设计精致、体积轻盈、操作简便的全屋智能家居控制面板,已经成为众多家庭的新宠。这种高效、直观的智能化的解决方…...
CSS3新增盒子属性(三)
1、CSS3新增盒子属性 1.1 box-sizing 设置盒子的大小。 content-box:设置内容区的大小;border-box:设置盒子的总大小。 <!DOCTYPE html> <html lang"zh-CN"><head><meta charset"UTF-8"><t…...

Manus在虚拟现实仿真模拟中的应用案例分享
Manus虚拟现实手套作为一种高精度的人机交互设备,在仿真模拟领域展现出了巨大的应用潜力。通过提供实时、准确的手指动作捕捉数据,Manus手套为多个行业带来了前所未有的仿真体验,推动了技术发展和应用创新。 技术特点 1. 高精度手指跟踪 Ma…...

大数据-201 数据挖掘 机器学习理论 - 决策树 局部最优 剪枝 分裂 二叉分裂
点一下关注吧!!!非常感谢!!持续更新!!! 目前已经更新到了: Hadoop(已更完)HDFS(已更完)MapReduce(已更完&am…...
Scala 的trait
在Scala中,trait是一种特殊概念。trait可以作为接口,同时也可以定义抽象方法。类使用extends继承trait,在Scala中,无论继承类还是继承trait都用extends关键字。在Scala中, 类继承trait后必须实现其中的抽象方法&#x…...

vue3官方示例-简单的 markdown 编辑器。
官方示例不能直接粘贴使用,故自己补了些代码。方便初学者学习,节省时间,提高学习效率。 1、html代码: <!doctype html> <html lang"en"> <head><meta charset"UTF-8"><meta nam…...

Linux标准I/O库汇总整理
Linux标准I/O库(Standard I/O Library)是C标准库的一部分,提供了一系列用于文件输入输出的高级接口。这些接口通常比低级别的系统调用更易于使用,但也可能带来额外的性能开销。下面是Linux标准I/O库的汇总整理,包括常见…...

BGP路由优选+EVPN
BGP 的路由优选规则是一套多步决策链,用来确定在多个可行路由中选择最优的路由。BGP 是一种路径向量协议,通过这些优选规则,网络管理员可以控制数据流量的流向,确保网络的稳定性和效率。下面以一个实例来详细说明 BGP 的优选规则及…...
牛客练习赛131(未补)
A-小H学语文 题意:木板数量为m,想让mmh(min)最大,找出这几块木板 分析:让木板从大到小排序,找到最大的体积,将之前的木板按序列输出 代码: #include<bits/stdc.h> using n…...

功能更新丨AI黑科技助燃VR全景新势能
随着VR全景市场需求不断扩大, 为更好地赋能合作商业务发展, 酷雷曼积极推进产品技术迭代, 融合VR虚拟现实和AI人工智能, 重磅推出6大AI黑科技, 让VR全景内容更丰富、创作更加高效! 新功能怎么用&#…...
JavaCV学习第一课
1、 JavaCV [1] 是一款基于JavaCPP [2]调用方式(JNI的一层封装),由多种开源计算机视觉库组成的包装库,封装了包含FFmpeg、OpenCV、tensorflow、caffe、tesseract、libdc1394、OpenKinect、videoInput和ARToolKitPlus等在内的计算…...

Java第二阶段---16字符串---第一节 String
1.特性介绍 String 类位于 java.lang 包中,无需引入,直接使用即可。 String 类是由 final 修饰的,表示String 类是一个最终类,不能够被继承。 String 类构建的对象不可再被更改 示例 package com.cyx.string;public class Ex…...

<十六>Ceph mon 运维
Ceph 集群有故障了,你执行的第一个运维命令是什么? 我猜测是ceph -s 。无论执行的第一个命令是什么,都肯定是先检查Mon。 在开始之前我们有必要介绍下Paxos协议,毕竟Mon就是靠它来实现数据唯一性。 一: Paxos 协议 1…...

【网络安全初识】——互联网发展史
个人主页:兜里有颗棉花糖 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 兜里有颗棉花糖 原创 收录于专栏【网络安全】 本专栏旨在分享学习网络安全的一些学习笔记,欢迎大家在评论区交流讨论💌 ipconfig:显示当…...
Windows和Linux内存共享机制
Windows和Linux内存共享机制 引言1.Windows写操作读操作 2.Linux写操作读操作 3.Shell使用 tmux 运行 write 和 read说明 引言 在嵌入式开发领域,内存共享机制作为不同操作系统间实现高效数据交换的重要手段,尤其在对实时性和可靠性要求极高的环境中更为…...
windows@命令行中获取环境变量取值不展开取值(原值)
文章目录 命令行中获取环境变量取值获取不展开的值具体实现注解 封装为函数版本1版本2 命令行中获取环境变量取值 这里主要讨论获取未展开的值本来获取未展开的值应该作为默认选项,至少有合适的api方便直接调用,但是不知道微软怎么想的,让这个任务变得不直接 获取不展开的值 …...

如何找到多平台内容爆款进行批量复刻?
为了进一步扩大品牌社媒影响力,在消费者做决策的时候,能够第一时间出现在首选位置。持续在抖音、小红书、b站、公众号等各大社媒平台,产生连续的、正向的高质量品牌曝光,是非常重要的。如何进行这种多平台品牌影响力的提升呢&…...

【UML】- 用例图(结合银行案例解释其中的奥义)
目录 一、相关介绍 作用: 组成: 关系 二、使用具体银行案例解释各组成部分的含义 1、系统 2、参与者 3、用例 4、关联关系 5、扩展关系 6、泛化(继承)关系 三、成品 一、相关介绍 作用: 用例图可以描述一个…...

浅谈UI自动化
⭐️前言⭐️ 本篇文章围绕UI自动化来展开,主要内容包括什么是UI自动化,常用的UI自动化框架,UI自动化原理等。 🍉欢迎点赞 👍 收藏 ⭐留言评论 🍉博主将持续更新学习记录收获,友友们有任何问题…...
Android Wi-Fi 连接失败日志分析
1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分: 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析: CTR…...
HTML 语义化
目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案: 语义化标签: <header>:页头<nav>:导航<main>:主要内容<article>&#x…...

css实现圆环展示百分比,根据值动态展示所占比例
代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...

MODBUS TCP转CANopen 技术赋能高效协同作业
在现代工业自动化领域,MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步,这两种通讯协议也正在被逐步融合,形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...
Java入门学习详细版(一)
大家好,Java 学习是一个系统学习的过程,核心原则就是“理论 实践 坚持”,并且需循序渐进,不可过于着急,本篇文章推出的这份详细入门学习资料将带大家从零基础开始,逐步掌握 Java 的核心概念和编程技能。 …...
深度学习之模型压缩三驾马车:模型剪枝、模型量化、知识蒸馏
一、引言 在深度学习中,我们训练出的神经网络往往非常庞大(比如像 ResNet、YOLOv8、Vision Transformer),虽然精度很高,但“太重”了,运行起来很慢,占用内存大,不适合部署到手机、摄…...

Elastic 获得 AWS 教育 ISV 合作伙伴资质,进一步增强教育解决方案产品组合
作者:来自 Elastic Udayasimha Theepireddy (Uday), Brian Bergholm, Marianna Jonsdottir 通过搜索 AI 和云创新推动教育领域的数字化转型。 我们非常高兴地宣布,Elastic 已获得 AWS 教育 ISV 合作伙伴资质。这一重要认证表明,Elastic 作为 …...
书籍“之“字形打印矩阵(8)0609
题目 给定一个矩阵matrix,按照"之"字形的方式打印这个矩阵,例如: 1 2 3 4 5 6 7 8 9 10 11 12 ”之“字形打印的结果为:1,…...
跨平台商品数据接口的标准化与规范化发展路径:淘宝京东拼多多的最新实践
在电商行业蓬勃发展的当下,多平台运营已成为众多商家的必然选择。然而,不同电商平台在商品数据接口方面存在差异,导致商家在跨平台运营时面临诸多挑战,如数据对接困难、运营效率低下、用户体验不一致等。跨平台商品数据接口的标准…...
2025.6.9总结(利与弊)
凡事都有两面性。在大厂上班也不例外。今天找开发定位问题,从一个接口人不断溯源到另一个 接口人。有时候,不知道是谁的责任填。将工作内容分的很细,每个人负责其中的一小块。我清楚的意识到,自己就是个可以随时替换的螺丝钉&…...