Java核心类——8.BigDecimal
java.math.BigDecimal使用
在金融、电商等对数值精度要求极高的领域,Java的基本浮点类型(float、double)往往无法满足需求,因为它们会产生精度丢失的问题。而java.math.BigDecimal类提供了完全精确的十进制浮点运算解决浮点精度丢失。
BigDecimal构造
BigDecimal其内部通过BigInteger存储整数部分,再通过scale(小数位数)来确定小数点位置,从而能够表示任意精度的小数。
创建BigDecimal的正确方式是使用字符串构造,避免使用double构造(否则会带入精度误差):
// 推荐方式:通过字符串创建
BigDecimal correct = new BigDecimal("0.1");
// 不推荐:double本身的精度问题会被带入
BigDecimal incorrect = new BigDecimal(0.1); // 实际值可能是0.1000000000000000055...
小数位数(scale)
scale是BigDecimal的核心属性,代表小数部分的位数:
BigDecimal d1 = new BigDecimal("123.45");
BigDecimal d2 = new BigDecimal("123.4500");
BigDecimal d3 = new BigDecimal("12345");
System.out.println(d1.scale()); // 2(两位小数)
System.out.println(d2.scale()); // 4(四位小数)
System.out.println(d3.scale()); // 0(整数)
通过stripTrailingZeros()方法可以移除末尾多余的0,同时自动调整scale:
BigDecimal d = new BigDecimal("123.4500").stripTrailingZeros();
System.out.println(d.scale()); // 2(移除两个0后保留两位小数)
当scale为负数时,表示整数部分末尾有对应数量的0:
BigDecimal d = new BigDecimal("1234500").stripTrailingZeros();
System.out.println(d.scale()); // -2(表示整数1234500末尾有2个0)
精度控制与四舍五入
setScale(int newScale, RoundingMode mode)方法用于调整精度,其中RoundingMode指定舍入规则:
import java.math.RoundingMode;
BigDecimal d = new BigDecimal("123.456789");
// 保留4位小数,四舍五入
BigDecimal rounded = d.setScale(4, RoundingMode.HALF_UP); // 123.4568
// 保留4位小数,直接截断
BigDecimal truncated = d.setScale(4, RoundingMode.DOWN); // 123.4567
常用的RoundingMode包括:
HALF_UP:四舍五入(最常用)DOWN:直接截断UP:向上进位HALF_EVEN:银行家舍入法(偶数位四舍五入)
运算规则
BigDecimal的四则运算通过实例方法实现,其中除法需要特别注意精度设置:
BigDecimal a = new BigDecimal("123.456");
BigDecimal b = new BigDecimal("23.456789");
// 加、减、乘运算(精度自动维护)
BigDecimal sum = a.add(b);
BigDecimal diff = a.subtract(b);
BigDecimal product = a.multiply(b);
// 除法必须指定精度和舍入模式(否则可能因除不尽报错)
BigDecimal quotient = a.divide(b, 10, RoundingMode.HALF_UP); // 保留10位小数
通过divideAndRemainder()可同时获取商和余数:
BigDecimal n = new BigDecimal("12.345");
BigDecimal m = new BigDecimal("0.12");
BigDecimal[] dr = n.divideAndRemainder(m);
System.out.println(dr[0]); // 商:102
System.out.println(dr[1]); // 余数:0.105
比较与相等判断
关键注意点:equals()方法不仅比较值,还会比较scale,而compareTo()仅比较数值大小:
BigDecimal d1 = new BigDecimal("123.456");
BigDecimal d2 = new BigDecimal("123.45600");
System.out.println(d1.equals(d2)); // false(scale不同:3 vs 5)
System.out.println(d1.compareTo(d2) == 0); // true(数值相等)
注意:始终使用compareTo()比较两个BigDecimal的值,返回值含义:
- 0:相等
- 1:当前对象更大
- -1:当前对象更小
总结
BigDecimal用于表示精确的小数,解决了Java浮点类型的精度丢失问题。- 比较BigDecimal的值是否相等,必须使用compareTo()而不能使用equals()。
Java核心类——8.BigDecimal的更多相关文章
- 从字节码和JVM的角度解析Java核心类String的不可变特性
1. 前言 最近看到几个有趣的关于Java核心类String的问题. String类是如何实现其不可变的特性的,设计成不可变的好处在哪里. 为什么不推荐使用+号的方式去形成新的字符串,推荐使用Stri ...
- Java核心类
Java核心类的学习: 常用类库 io流 集合 多线程 网络编程 调试与优化 XML和JSON 枚举.注解和反射 设计模式
- Day1 面向对象编程与Java核心类
this变量 在方法内部,可以使用一个隐含的变量this,它始终指向当前实例.如果没有命名冲突,可以省略this. 但是,如果有局部变量和字段重名,那么局部变量优先级更高,就必须加上this. 构造方 ...
- java常用类之BigDecimal
BigDecimal 小数计算丢失精度问题 在计算机中,所有文件都是以二进制存储的,数字运算也是使用二进制进行计算的,因为计算机中不存在小数点,所以我们通常说的浮点数如float.double都是计算 ...
- 【Java常用类】BigDecimal
BigDecimal 一般的Float类和Double类可以用来做科学计算或工程计算,但在商业计算中, 要求数字精度比较高,故用到java.math.BigDecimal类. BigDecimal类支 ...
- Java工具类之——BigDecimal运算封装(包含金额的计算方式)
日常对于金额计算,应该都是用的BigDecimal, 可是苦于没有好的工具类方法,现在贡献一个我正在用的对于数字计算的工具类,项目中就是用的这个,简单粗暴好用,话不多说,代码奉上(该工具类需要引入g ...
- 14-03 java BigInteger类,BigDecimal类,Date类,DateFormat类,Calendar类
BigInteger类 发 package cn.itcast_01; import java.math.BigInteger; /* * BigInteger:可以让超过Integer范围内的数据进 ...
- Java——String类中的compareTo方法总结
String类的定义: java.lang 类 String java.lang.Object java.lang.String 所有已实现的接口:Serializable, C ...
- Java基础学习笔记二十三 Java核心语法之反射
类加载器 类的加载 当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,链接,初始化三步来实现对这个类进行初始化. 加载就是指将class文件读入内存,并为之创建一个Class对象.任 ...
- 到头来还是逃不开Java - Java13核心类
Java13核心类 没有特殊说明,我的所有学习笔记都是从廖老师那里摘抄过来的,侵删 引言 兜兜转转到了大四,学过了C,C++,C#,Java,Python,学一门丢一门,到了最后还是要把Java捡起来 ...
随机推荐
- Linux下部署Spring Boot 项目 jar包
打jar包 在IDEA 2020的最右侧边,选中Maven ,然后双击Lifecycle标签下的package即开始打包,之后就会在target目录下生成jar包. 注意,需要修改pom.xml ...
- mysql安全小结
sql的注入是一个很困扰人的问题,一些恶意攻击者可以利用sql注入来获取甚至是修改数据库中的信息,尤其是一些比较敏感的密码一类的数据. sql注入主要利用mysql 的注释将后续应正常执行的语句注释掉 ...
- 「Log」NOIP 2023 游记
Day 0 打了大半天板子,然后开摆. 打块,快下班的时候玩了猜词游戏. 回家睡大觉. Day 1 早上起床状态良好,收拾收拾就出门了,跟爸妈吃了肯德基,然后坐车到三校区. 才看到 cc0000 之前 ...
- K8s新手系列之CronJob
概述 官方文档:https://kubernetes.io/zh-cn/docs/concepts/workloads/controllers/cron-jobs/ CronJob控制器以 Job控制 ...
- 【运维必看】雷池社区版自动 SSL:从申请到部署全自动化,让证书续期从此 “无感”!
雷池社区版自动SSL 作者:夜猫(社区9群) 正常安装雷池,并配置站点,暂时不配置ssl 不使用雷池自带的证书申请. 安装(acme.sh),使用域名验证方式生成证书 先安装gityum instal ...
- C#实现语音预处理:降噪、静音检测、自动增益(附Demo源码)
无论是在音视频录制系统,还是音视频通话系统.或视频会议系统中,对从麦克风采集到的说话的声音数据进行预处理,都是是非常必要的. 语音数据预处理主要包括:降噪(Noise Reduction).静音检 ...
- DTALK直播预约 | 深度解析大资管行业数字化转型
在<商业银行理财业务监督管理办法><关于规范金融机构资产管理业务的指导意见>等理财新规.资管新规的要求下,大资管行业结构持续优化,存量金融风险明显收敛.此外,也促使资管行业在产 ...
- 八、make编译输出重定向
4.编译输出重定向 将 make 命令的标准输出(stdout)和标准错误输出(stderr)重定向到文件,以便于查看编译日志,快速分析定位问题. 1.重定向到同一个文件 语法: make > ...
- .NET Core 微服务架构学习与实践系列文章目录
一.为啥要总结和收集这个系列? 2018年离开了原来的Team加入了新的Team,开始做Java微服务的开发工作,接触了Spring Boot, Spring Cloud等技术栈,对微服务这种架构有了 ...
- http流量镜像
http流量镜像 "流量镜像"是指将网络中的数据流量复制一份,并将这份复制流量发送到另一个目的地(如监控.分析或安全检测系统).这项技术常用于网络安全.故障排查.业务灰度发布等场景 ...