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×103??),可表示極大或極小的數(如?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.13)
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
英文地址,請注明出處:http://en.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;以…