当前位置: 首页 > article >正文

BigDecimal的使用

概述

BigDecimal是Java在java.math包中提供的一个API类,主要用于对超过16位有效位的数进行精确的运算。在商业计算、金融计算等需要高精度数值处理的场景中,BigDecimal显得尤为重要。但是BigDecimal是一个对象,不能直接使用传统的+、-、*、/等算术运算符进行数学运算,而必须调用其相对应的方法。本文是对BigDecimal的简单介绍。

构造方法

BigDecimal提供了多个构造方法,以便根据不同的需求创建对象:

BigDecimal(int)

使用int创建BigDecimal对象

BigDecimal(double)

使用double创建BigDecimal对象,但需要注意的是,由于double类型的精度限制,这种方法可能会导致结果有一定的不可预知性,因此通常不推荐使用

BigDecimal(long)

使用long创建BigDecimal对象

BigDecimal(String)

使用String创建BigDecimal对象

加、减、乘、除四则运算

1. BigDecimal加法

add(BigDecimal)

2. BigDecimal减法

subtract(BigDecimal)

3. BigDecimal乘法

multiply(BigDecimal)

4. BigDecimal除法

divide(BigDecimal)

对于除法需要注意的是,除法运算时可能会出现无法除尽的情况,此时需要指定保留的小数位数和舍入模式,否则会抛出ArithmeticException异常。

一下是除法使用的3种情况:

//1.可以除尽不抛异常
new BigDecimal(1).divide(new BigDecimal(2));

//2.存在除不尽的情况抛ArithmeticException异常
new BigDecimal(1).divide(new BigDecimal(3));
//java.lang.ArithmeticException: Non-terminating decimal expansion; 
//no exact representable decimal result.

//3.传入四舍五入,保留两位有效数字
new BigDecimal(1).divide(new BigDecimal(3),2,BigDecimal.ROUND_HALF_UP);

使用示例

//计算表达式:3+4*5-6/2 = 20
BigDecimal v2 = new BigDecimal(2);
BigDecimal v3 = new BigDecimal(3);
BigDecimal v4 = new BigDecimal(4);
BigDecimal v5 = new BigDecimal(5);
BigDecimal v6 = new BigDecimal(6);
BigDecimal v = v3.add(v4.multiply(v5)).subtract(v6.divide(v2));
System.out.println(v);

需要注意的是BigDecimal加减乘除的执行顺序与它们的算数优先级无关,只和方法的调用顺序有关。

其它方法

BigDecimal比较大小

BigDecimal v2 = new BigDecimal(2);
BigDecimal v3 = new BigDecimal(3);
System.out.println(v2.compareTo(v3));

BigDecimal比较大小使用compareTo()方法,如v2.compareTo(v3):v2和v3相等返回0,v2大于v3返回1,v2小于v3返回-1。

注意不要使用equals()比较BigDecimal的大小,在进行等值比较时,由于BigDecimal的equals()方法会同时比较值的大小和精度,因此可能会与预期不符。如下面两个值会被判定为不相等。

BigDecimal v1 = new BigDecimal("1.0");
BigDecimal v2 = new BigDecimal("1.00");
System.out.println(v1.equals(v2));
//输出false

绝对值

abs()

浮点数初始化

浮点数初始化可以使用BigDecimal.valueOf(),浮点数初始化可能会又精度问题,使用BigDecimal.valueOf()方法则不会有问题,看看它的源码就知道了,实际上是内部把double类型转成了String类型,所以才能安全地初始化。

public static BigDecimal valueOf(double var0) {
    return new BigDecimal(Double.toString(var0));
}

舍入模式

BigDecimal共有8种舍入模式:

ROUND_UP

向远离零的方向舍入。舍弃非零部分,并将非零舍弃部分相邻的一位数字加一。

ROUND_DOWN

向接近零的方向舍入。舍弃非零部分,同时不会非零舍弃部分相邻的一位数字加一,采取截取行为。

ROUND_CEILING

向正无穷的方向舍入。如果为正数,舍入结果同 ROUND_UP 一致;如果为负数,舍入结果同 ROUND_DOWN 一致。注意:此模式不会减少数值大小。

ROUND_FLOOR

向负无穷的方向舍入。如果为正数,舍入结果同 ROUND_DOWN 一致;如果为负数,舍入结果同 ROUND_UP 一致。注意:此模式不会增加数值大小。

ROUND_HALF_UP

向 最接近的数字舍入,如果与两个相邻数字的距离相等,则为向上舍入的舍入模式。如果舍弃部分 >= 0.5,则舍入行为与 ROUND_UP 相同;否则舍入行为与 ROUND_DOWN 相同。这种模式也就是我们常说的我们的 四舍五入。

ROUND_HALF_DOWN

向 最接近的数字舍入,如果与两个相邻数字的距离相等,则为向下舍入的舍入模式。如果舍弃部分 > 0.5,则舍入行为与 ROUND_UP 相同;否则舍入行为与 ROUND_DOWN 相同。这种模式也就是我们常说的我们的五舍六入。

ROUND_HALF_EVEN

向最接近的数字舍入,如果与两个相邻数字的距离相等,则相邻的偶数舍入。如果舍弃部分左边的数字奇数,则舍入行为与 ROUND_HALF_UP 相同;如果为偶数,则舍入行为与 ROUND_HALF_DOWN 相同。注意:在重复进行一系列计算时,此舍入模式可以将累加错误减到最小。此舍入模式也称为 “银行家舍入法”,主要在美国使用。四舍六入,被舍位为 5 时两种情况,如果前一位为奇数,则入位,否则舍去。

ROUND_UNNECESSARY

断言请求的操作具有精确的结果,因此不需要舍入。如果对获得精确结果的操作指定此舍入模式,则抛出异常。

总结

综上所述,BigDecimal是Java中处理高精度数值的重要工具,通过合理使用其构造方法和数学运算方法,可以满足商业计算、金融计算等场景对高精度数值处理的需求。

参考

BigDecimal的8种RoundingMode(舍入模式)


http://www.kler.cn/news/318218.html

相关文章:

  • Vue.js props 子组件可以从父组件接收数据(通过 props)并可以向父组件发送事件(通过 $emit)
  • 力扣206.反转链表
  • 24/9/24 算法笔记 超参数优化算法
  • 模型验证 — 交叉验证Cross Validation的方法
  • 大数据新视界 --大数据大厂之算法在大数据中的核心作用:提升效率与智能决策
  • 【linux】file命令
  • 数据篇| 关于Selenium反爬杂谈
  • Python3将Excel数据转换为文本文件
  • 【鸿蒙 HarmonyOS NEXT】组件嵌套滚动:nestedScroll
  • 【html】基础(二)
  • 量化交易----数据透视表----融资融券优惠代码
  • 响应式布局-媒体查询父级布局容器
  • spring boot导入多个配置文件
  • #C++ enum枚举
  • Qt/C++ 多线程同步机制详解及应用
  • Shiro-550—漏洞分析(CVE-2016-4437)
  • 详解QT插件机制
  • ARM/Linux嵌入式面经(三三):大疆
  • zabbix email 告警
  • [大语言模型-论文精读] ACL2024-长尾知识在检索增强型大型语言模型中的作用
  • Invalid Executable The executable contains bitcode
  • 报错error: RPC failed,curl 16 Error in the HTTP2 framing layer解决方法
  • 自动化学习3:日志记录及测试报告的生成--自动化框架搭建
  • 数据库课程 CMU15-445 2023 Fall Project-2 Extendible Hash Index
  • WebAssembly (Wasm) 与 JavaScript 字符串交互
  • shardingjdbc分库分表原理
  • 实战16-RVP定义完成适配
  • rocky9.2的lvs的NAT模式下的基本使用的详细示例
  • SpringBoot使用@Async注解,实现异步任务
  • 002.k8s(Kubernetes)一小时快速入门(先看docker30分钟)