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捡起来 ...
随机推荐
- 注解@Transactional事务失效的常见场景
在<Spring Boot事务管理>中,小编介绍了注解@Transactional的基本属性和使用方法,这里介绍事务失效的八种场景,使大家对注解@Transactional有一个更深刻的认 ...
- Spring注解之自定义注解入门
目录 前言 注解是什么 自定义注解 元注解 @Target @Retention @Documented @Inherited 结束语 Reference 前言 在业务开发过程中,Spring 框 ...
- RAG越来越不准?一文详解元数据与标签的系统优化方法(附完整流程图+实用提示词)
你是不是也遇到过这样的场景? 公司刚花大钱上线AI知识库,结果AI助手总是"答非所问",文档明明都上传了,关键时刻还是找不到想要的答案: 苦心搭了一两个月RAG系统,老板随便一问, ...
- SpringBoot的学习
SpringBoot SpringBoot最核心的东西:自动装配!!! 很重要! 以及他的SpringApplication.run(); 方法 配置用什么写:可以用xml, 和springboot自 ...
- SenseVoice部署,并调用api接口
目录 安装Python 代码下载 虚拟环境 安装依赖 下载模型 修改启用webui.py 启用api.py 安装Python 这个网上找下教程安装下就可以,版本应该没有什么要求,我装的是3.10.7 ...
- 简单的php奥运倒计时牌
1 <?php 2 3 date_default_timezone_set ( "Asia/Shanghai" ); 4 $kaimu = mktime ( 4, 0, 0, ...
- C++ set/multiset容器 学习总结
-------------------------------------set/multiset容器 set/multiset特性 set/multiset的特性是所有元素会根据元素的值自动进行排序 ...
- MKL库解线性最小二乘问题(LAPACKE_dgels)
LAPACK(Linear Algebra PACKage)库,是用Fortran语言编写的线性代数计算库,包含线性方程组求解(AX=B).矩阵分解.矩阵求逆.求矩阵特征值.奇异值等.该库用BLAS库 ...
- 利用Python调用outlook自动发送邮件
↓↓↓欢迎关注我的公众号,在这里有数据相关技术经验的优质原创文章↓↓↓ 使用Python发送邮件有两种方式,一种是使用smtp调用邮箱的smtp服务器,另一种是直接调用程序直接发送邮件.而在outlo ...
- [Compose Multiplatform Desktop] 比官方更好的Compose预览
前提概要 Compose Multiplatform 是从 Android 的 Jetpack Compose 发展而来的. 所以 Compose 在 Android 上功能最完善,其次是 Deskt ...