BigDecimal(用于处理超出double范围的浮点数)

BigDecimal 是 Java 中 java.math 包提供的高精度十进制浮点数类,专为解决基本类型(float/double)的精度缺陷而设计,广泛用于金融、科学计算等对精度要求极高的场景。以下从核心特性、使用方法、常见问题对比、注意事项等方面详细介绍:

一、核心特性

  1. 任意精度
    不像 double(64 位,约 15-17 位有效数字)有固定精度限制,BigDecimal 可通过 MathContext 或 setScale 自定义精度,理论上支持无限精度(仅受内存限制)。

  2. 精确十进制表示
    double 是二进制浮点数,无法精确表示如 0.1 这样的十进制小数(会存储为近似值),而 BigDecimal 基于十进制算术,可精确存储和计算小数。

  3. 可控舍入模式
    支持 8 种舍入规则(如四舍五入、向上取整、向下取整等),满足不同场景的精度控制需求(如货币计算需精确到分)。

  4. 超大数值范围
    突破 double 的范围限制(double 最大约 1.8×10³⁰⁸),可表示极大或极小的数(如 10^10000 或 10^-10000)。

二、基本使用方法

1. 初始化(关键!避免精度陷阱)

BigDecimal 有多种构造方法,强烈推荐用字符串初始化,避免因 double 本身的精度误差导致问题:

import java.math.BigDecimal;// 正确方式:字符串构造(无精度损失)
BigDecimal num1 = new BigDecimal("0.1"); // 精确表示0.1
BigDecimal num2 = new BigDecimal("100.0000000001"); // 精确存储多位小数// 错误方式:double构造(可能引入精度误差)
BigDecimal bad1 = new BigDecimal(0.1); // 实际存储的是0.1的二进制近似值(约0.1000000000000000055...)
BigDecimal bad2 = new BigDecimal(1.234567890123456789); // 超过double精度,会被截断// 其他方式:整数或长整数构造
BigDecimal num3 = new BigDecimal(123); // 等价于new BigDecimal("123")
BigDecimal num4 = new BigDecimal(1234567890123456789L); // 大整数
2. 核心运算方法

BigDecimal 不支持 +-*/ 等运算符,需通过以下方法进行运算,且运算结果需用新变量接收(原对象不变):

方法功能示例(num1=0.1,num2=0.2)
add(BigDecimal)加法num1.add(num2) → 0.3
subtract(BigDecimal)减法num2.subtract(num1) → 0.1
multiply(BigDecimal)乘法num1.multiply(num2) → 0.02
divide(BigDecimal)除法(需指定舍入模式)num1.divide(num2, 2, RoundingMode.HALF_UP) → 0.50
pow(int)幂运算num1.pow(3) → 0.001(0.1³)
3. 精度与舍入控制
(1)设置小数位数(setScale
BigDecimal num = new BigDecimal("3.1415926");// 保留2位小数,四舍五入(RoundingMode.HALF_UP)
BigDecimal scaled1 = num.setScale(2, RoundingMode.HALF_UP); // 3.14// 保留4位小数,向上取整(RoundingMode.UP)
BigDecimal scaled2 = num.setScale(4, RoundingMode.UP); // 3.1416(第5位是9,向上进1)// 保留1位小数,向下取整(RoundingMode.DOWN)
BigDecimal scaled3 = num.setScale(1, RoundingMode.DOWN); // 3.1(直接截断)
(2)常用舍入模式(RoundingMode
模式说明示例(保留 1 位小数)
HALF_UP四舍五入(最常用)3.14 → 3.1;3.15 → 3.2
UP向上取整(远离零)3.11 → 3.2;-3.11 → -3.2
DOWN向下取整(趋向零)3.19 → 3.1;-3.19 → -3.1
HALF_DOWN五舍六入3.15 → 3.1;3.16 → 3.2
CEILING向正无穷取整3.1 → 4.0;-3.1 → -3.0
FLOOR向负无穷取整3.1 → 3.0;-3.1 → -4.0
4. 比较大小(compareTo

不能用 == 或 equals 比较equals 会严格比较精度,如 0.1 与 0.10 视为不等),需用 compareTo

BigDecimal a = new BigDecimal("0.1");
BigDecimal b = new BigDecimal("0.10");
BigDecimal c = new BigDecimal("0.2");// compareTo 返回值:
// 0 → 相等;1 → a > b;-1 → a < b
System.out.println(a.compareTo(b)); // 0(数值相等,忽略精度差异)
System.out.println(a.compareTo(c)); // -1(0.1 < 0.2)
System.out.println(c.compareTo(a)); // 1(0.2 > 0.1)// 错误:equals 会比较精度(0.1 与 0.10 精度不同,返回false)
System.out.println(a.equals(b)); // false
5. 转换为其他类型
BigDecimal num = new BigDecimal("123.456");// 转换为基本类型(可能溢出,需谨慎)
double d = num.doubleValue(); // 123.456(可能损失精度)
long l = num.longValue(); // 123(截断小数部分)// 转换为字符串(推荐,无精度损失)
String s = num.toString(); // "123.456"

三、与 double 的对比(解决哪些问题?)

场景double 问题BigDecimal 解决方案
0.1 + 0.2结果为 0.30000000000000004(精度损失)结果为 0.3(精确计算)
货币计算(如分)无法精确表示分(如 0.01 存储为近似值)可精确表示 0.01,避免金额误差
超大 / 超小数值超过范围会溢出为 Infinity 或 0可表示任意大小数值(受内存限制)
舍入规则控制仅支持默认舍入,无法自定义8 种舍入模式,灵活控制精度

四、注意事项(避坑指南)

  1. 初始化必须用字符串
    用 double 构造 BigDecimal 会继承 double 的精度误差(如 new BigDecimal(0.1) 实际是 0.1000000000000000055...),务必用 new BigDecimal("0.1")

  2. 除法必须指定舍入模式
    当除法无法整除时(如 1 ÷ 3),不指定舍入模式会抛出 ArithmeticException

    // 错误:1 ÷ 3 无法整除,无舍入模式会抛异常
    new BigDecimal("1").divide(new BigDecimal("3")); // 正确:指定舍入模式和精度
    new BigDecimal("1").divide(new BigDecimal("3"), 2, RoundingMode.HALF_UP); // 0.33
    
  3. 避免频繁创建对象
    BigDecimal 是不可变对象(运算后生成新对象),频繁运算会产生大量临时对象,影响性能。可重用对象或使用 MathContext 控制精度。

  4. 谨慎处理 equals 方法
    equals 会比较数值和精度(如 0.1 与 0.10 视为不等),比较数值相等需用 compareTo

  5. 性能权衡
    BigDecimal 运算效率远低于 double,非高精度场景(如普通科学计算)无需使用。

五、典型应用场景

  1. 金融 / 货币计算:如银行转账、税费计算(需精确到分,避免一分钱误差)。
  2. 高精度科学计算:如物理、数学中的精确数值模拟(需保留多位有效数字)。
  3. 超大数值处理:如密码学中的大整数运算、天文数据(超过 double 范围)。

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

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

相关文章

Nginx 优化

文章目录1、隐藏版本号2、修改用户与组3、缓存时间4、日志切割5、连接超时6、更改进程数7、配置网页8、防盗链1、隐藏版本号 隐藏nginx的版本号&#xff0c;为了防止恶意用户利用已知漏洞进行攻击 ## 查看版本号 curl -I http://192.168.10.23方法一&#xff1a;修改配置文件…

基于多模态与主动学习的车船飞机图像识别系统研究与应用技术方案

技术方案 一、技术背景与研究现状 图像识别是计算机视觉的核心任务之一&#xff0c;随着深度学习的发展&#xff0c;基于 卷积神经网络&#xff08;CNN&#xff09; 与 视觉Transformer&#xff08;ViT&#xff09; 的图像分类方法已成为主流。 根据《图像分类技术选型——截止…

Word2Vec词嵌入技术和动态词嵌入技术

Word2Vec&#xff08;Word to Vector&#xff09;是 2013 年由 Google 团队提出的无监督词嵌入模型&#xff0c;是一种静态词嵌入技术&#xff0c;核心目标是将自然语言中的离散词汇映射为低维、稠密的实数向量&#xff08;即 “词向量”&#xff09;&#xff0c;让向量空间的距…

Netty从0到1系列之Netty逻辑架构【上】

文章目录一、Netty逻辑架构【上】1.1 网络通信层1.1.1 BootStrap & ServerBootStrap1. ✅核心方法链与配置2. ✅ 架构与流程3. ✅ 底层实现与原理分析4. ✅ 实践经验与总结1.1.2 Channel1.2 事件调度层1.2.1 事件调度层概述1.2.2 EventLoop【事件循环】1.2.3 EventLoopGrou…

Spring Cloud 高频面试题详解(含代码示例与深度解析)

文章目录Spring Cloud 高频面试题详解&#xff08;含代码示例与深度解析&#xff09;1. 什么是 Spring Cloud&#xff1f;它与 Spring Boot 有什么关系&#xff1f;2. 服务发现&#xff1a;Eureka 和 Nacos 的区别与选型&#xff1f;Eureka 示例与原理Eureka vs Nacos 对比表3.…

Ascend310B重构驱动run包

在Atlas 200I AI加速模块(Ascend310B)移植过程中如需要将自己编译的Image、dt.img及内核模块打包到启动镜像包中需要对"Ascend-hdk-310b-npu-driver-soc_<version>_linux-aarch64.run"(下面统称驱动run包)进行重构。下面将介绍如何重构run包。 重构驱动run包需…

Leecode hot100 - 287. 寻找重复数

题目描述 287. 寻找重复数 - 力扣&#xff08;LeetCode&#xff09; 定一个包含 n 1 个整数的数组 nums &#xff0c;其数字都在 [1, n] 范围内&#xff08;包括 1 和 n&#xff09;&#xff0c;可知至少存在一个重复的整数。 假设 nums 只有 一个重复的整数 &#xff0c;返…

机器人控制器开发(驱动层——奥比大白相机适配)

文章总览 编译OrbbecSDK_ROS2的代码 执行命令 colcon buildros2 launch orbbec_camera dabai.launch.py问题1&#xff1a; 运行时报错&#xff1a; [component_container-1] [ERROR] [1757153916.450795107] [camera.camera_container]: Failed to load library: Could not…

`vcpkg` 微软开源的 C/C++ 包管理工具的使用和安装使用spdlog

vcpkg 是 微软开源的 C/C 包管理工具&#xff0c;类似于 Python 的 pip、Node.js 的 npm、Rust 的 cargo。 它的主要作用是&#xff1a;帮助你快速下载、编译、安装和管理 C/C 第三方库&#xff0c;并自动配置到你的项目&#xff08;比如 Visual Studio、CMake、MSBuild&#x…

Mysql 幻读详解

我们来详细地聊一聊 MySQL InnoDB 中的“幻读”&#xff08;Phantom Read&#xff09;问题。这是一个在数据库事务隔离中非常核心且有时令人困惑的概念。 我会从定义、例子、原因以及解决方案几个方面来彻底讲清楚。 1. 什么是幻读&#xff1f; 官方定义&#xff1a;幻读指的…

如何生成 GitHub Token(用于 Hexo 部署):保姆级教程+避坑指南

如何生成 GitHub Token&#xff08;用于 Hexo 部署&#xff09;&#xff1a;保姆级教程避坑指南 前置说明&#xff1a;为什么需要 GitHub Token&#xff1f; 在使用 Hexo 部署博客到 GitHub Pages 时&#xff0c;你可能会遇到「密码验证失败」或「需要双重验证」的问题——这…

常用加密算法之 AES 简介及应用

相关系列文章 常用加密算法之 SM4 简介及应用常用加密算法之 RSA 简介及应用 引言 AES&#xff08;Advanced Encryption Standard&#xff0c;高级加密标准&#xff09;是一种​​广泛使用的对称分组加密算法​​&#xff0c;它使用相同的密钥进行加密和解密操作&#xff0c…

Java面试问题记录(一)

一、Java 核心基础与进阶1、我们知道 Java 中存在 “值传递” 和 “引用传递” 的说法&#xff0c;你能结合具体例子&#xff0c;说明 Java 到底是值传递还是引用传递吗&#xff1f;这背后涉及到 JVM 中哪些内存区域的交互&#xff1f;Java中只有值传递&#xff0c;不存在引用传…

Redis 主从复制、哨兵与 Cluster 集群部署

文章摘要 本文基于 VMware 虚拟机环境&#xff0c;详细讲解 Redis 高可用架构的核心组件与部署流程&#xff0c;涵盖三大核心模块&#xff1a;Redis 主从复制&#xff08;实现数据备份与读写分离&#xff09;、Redis 哨兵&#xff08;基于主从复制实现故障自动转移&#xff0c;…

ElementUI 中 validateField 对部分表单字段数组进行校验时多次回调问题

目录 方案一&#xff1a;循环调用 Promise.all 合并结果 方案二&#xff1a;直接传入数组字段 总结 在实际业务中&#xff0c;我们有时只需要对表单的部分字段进行校验。ElementUI 提供的 validateField 方法支持单个字段&#xff0c;也支持字段数组&#xff0c;但在使用时…

Visual Studio 2026 震撼发布!AI 智能编程时代正式来临

Visual Studio 2026 震撼发布&#xff01;AI 智能编程时代正式来临 Visual Studio 2026 Insider图标 开发者们的开发环境即将迎来前所未有的智能革命&#xff0c;微软用Visual Studio 2026 重新定义了编码体验。 2025年9月10日&#xff0c;微软正式推出了Visual Studio 2026 In…

Gamma AI:高效制作PPT的智能生成工具

你有没有过这种崩溃时刻&#xff1f;领导让你下午交一份产品介绍 PPT&#xff0c;你打开模板网站翻了半小时没找到合适的&#xff0c;好不容易选了个模板&#xff0c;又得手动调整文字间距、搭配图片&#xff0c;光是把数据做成图表就花了一小时&#xff0c;最后赶出来的 PPT 还…

Python副业新玩法:用Flask搭小程序后端,躺赚被动收入的秘密

凌晨1点&#xff0c;林浩合上电脑时&#xff0c;手机弹出一条微信消息——是上周帮一家社区水果店搭的小程序后端&#xff0c;商家发来了当月的服务费到账提醒。他靠在椅背上笑了&#xff1a;这是这个月第8笔“睡后收入”&#xff0c;加起来刚好覆盖了下个月的房贷。半年前&…

基于PyQt5和阿里云TTS的语音合成应用开发实战[附源码】

项目概述 本文将详细介绍一个基于PyQt5图形界面框架和阿里云TTS(Text-to-Speech)服务的语音合成桌面应用程序的开发过程。该应用提供了完整的文字转语音功能,包括多音色选择、参数调节、实时试听、语速调节和音频下载等特性。 技术栈 前端界面: PyQt5 语音合成: 阿里云TTS服…

基于esp32c3 rust embassy 的墨水屏程序

EPD Reader 基于ESP32-C3的电子墨水屏阅读器&#xff0c;支持ap 配网、sntp 时间同步、txt阅读、天气预报、显示节假日信息、农历显示、自动休眠、web配置等功能。这是在另一个项目 一个rust embassy esp32c3 的练习项目-CSDN博客的基础上修改的 。 界面比较粗糙&#xff0c;以…