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

高精度运算工具类

高精度运算工具类ArithTool 背景为什么要用高精度运算在Java中使用double或float进行浮点数运算时经常会遇到精度丢失的问题。这是因为计算机使用二进制存储浮点数而某些十进制小数如0.1无法被二进制精确表示。经典精度问题示例System.out.println(0.1 0.2); // 输出: 0.30000000000000004 System.out.println(1.0 - 0.9); // 输出: 0.09999999999999998 System.out.println(0.3 / 0.1); // 输出: 2.9999999999999996在金融计算、科学计算等场景下这种精度误差是不可接受的。BigDecimal类提供了任意精度的定点数表示是解决这一问题的标准方案。️ 完整代码import java.math.BigDecimal; import java.math.RoundingMode; import java.util.Objects; /** * 高精度运算工具类 * * p提供精确的浮点数运算包括加减乘除和四舍五入。 * 基于 {link BigDecimal} 实现避免 double/float 的精度丢失问题。/p * * pstrong适用场景/strong/p * ul * li金融金额计算价格、金额、汇率/li * li科学计算需要高精度结果/li * li任何不允许精度误算的数值运算/li * /ul * * pstrong使用示例/strong/p * pre * double result ArithTool.add(0.1, 0.2); // 结果: 0.3 * double price ArithTool.mul(19.99, 3); // 结果: 59.97 * double avg ArithTool.div(10, 3, 2); // 结果: 3.33保留2位小数 * /pre * * author lchhh0005 * version 2.0 */ public final class ArithTool { /** 默认除法运算精度小数点后10位 */ private static final int DEFAULT_DIV_SCALE 10; /** 私有构造方法防止实例化 */ private ArithTool() { throw new AssertionError(工具类禁止实例化); } /** * 精确的加法运算 * * p将两个 double 数值转换为 {link BigDecimal} 后相加 * 最后返回 double 类型的精确结果。/p * * param v1 被加数 * param v2 加数 * return 两个参数的和 * throws NumberFormatException 如果参数为 NaN 或 Infinity */ public static double add(double v1, double v2) { BigDecimal b1 convertToBigDecimal(v1); BigDecimal b2 convertToBigDecimal(v2); return b1.add(b2).doubleValue(); } /** * 精确的减法运算 * * param v1 被减数 * param v2 减数 * return 两个参数的差v1 - v2 * throws NumberFormatException 如果参数为 NaN 或 Infinity */ public static double subtract(double v1, double v2) { BigDecimal b1 convertToBigDecimal(v1); BigDecimal b2 convertToBigDecimal(v2); return b1.subtract(b2).doubleValue(); } /** * 精确的乘法运算 * * param v1 被乘数 * param v2 乘数 * return 两个参数的积 * throws NumberFormatException 如果参数为 NaN 或 Infinity */ public static double multiply(double v1, double v2) { BigDecimal b1 convertToBigDecimal(v1); BigDecimal b2 convertToBigDecimal(v2); return b1.multiply(b2).doubleValue(); } /** * 精确的除法运算默认精度 * * p当发生除不尽的情况时精确到小数点后10位之后的数字四舍五入。/p * * param v1 被除数 * param v2 除数 * return 两个参数的商 * throws ArithmeticException 如果除数为0 * throws IllegalArgumentException 如果参数为 NaN 或 Infinity */ public static double divide(double v1, double v2) { return divide(v1, v2, DEFAULT_DIV_SCALE); } /** * 精确的除法运算指定精度 * * p当发生除不尽的情况时由 scale 参数指定精度之后的数字四舍五入。/p * * param v1 被除数 * param v2 除数 * param scale 小数点后保留的位数必须 0 * return 两个参数的商 * throws ArithmeticException 如果除数为0 * throws IllegalArgumentException 如果 scale 0或参数为 NaN/Infinity */ public static double divide(double v1, double v2, int scale) { validateScale(scale); validateDivisor(v2); BigDecimal b1 convertToBigDecimal(v1); BigDecimal b2 convertToBigDecimal(v2); return b1.divide(b2, scale, RoundingMode.HALF_UP).doubleValue(); } /** * 四舍五入处理 * * p对指定数值进行四舍五入保留指定小数位数。/p * * param v 需要四舍五入的数字 * param scale 小数点后保留的位数必须 0 * return 四舍五入后的结果 * throws IllegalArgumentException 如果 scale 0或参数为 NaN/Infinity */ public static double round(double v, int scale) { validateScale(scale); BigDecimal b convertToBigDecimal(v); return b.setScale(scale, RoundingMode.HALF_UP).doubleValue(); } /** * 将 double 安全转换为 BigDecimal * * p使用 {link Double#toString(double)} 而非 {link BigDecimal#valueOf(double)} * 或直接构造避免浮点表示误差被保留。/p * * param value 待转换的 double 值 * return 对应的 BigDecimal 对象 * throws IllegalArgumentException 如果值为 NaN 或 Infinity */ private static BigDecimal convertToBigDecimal(double value) { if (Double.isNaN(value) || Double.isInfinite(value)) { throw new IllegalArgumentException( 非法数值: value 不接受 NaN 或 Infinity ); } return new BigDecimal(Double.toString(value)); } /** * 验证精度参数 * * param scale 待验证的精度值 * throws IllegalArgumentException 如果 scale 0 */ private static void validateScale(int scale) { if (scale 0) { throw new IllegalArgumentException( 精度必须为非负整数当前值: scale ); } } /** * 验证除数不为零 * * param divisor 除数 * throws ArithmeticException 如果除数为0 */ private static void validateDivisor(double divisor) { if (divisor 0.0) { throw new ArithmeticException(除数不能为0); } } } 主要优化点说明1.命名规范化原命名优化后说明subsubtract使用完整单词提高可读性mulmultiply同上divdivide同上DEF_DIV_SCALEDEFAULT_DIV_SCALE避免缩写语义更清晰2.常量命名与访问控制// 原代码 private static final int DEF_DIV_SCALE 10; // 优化后 private static final int DEFAULT_DIV_SCALE 10;使用全大写下划线的标准常量命名保持private访问控制防止外部修改3.构造方法强化// 原代码可被反射实例化 private ArithTool() { } // 优化后彻底防止实例化 private ArithTool() { throw new AssertionError(工具类禁止实例化); }4.BigDecimal.ROUND_HALF_UP 已废弃// 原代码已废弃 BigDecimal.ROUND_HALF_UP // 优化后推荐用法 RoundingMode.HALF_UP⚠️重要BigDecimal.ROUND_HALF_UP在 Java 9 中已被标记为Deprecated应使用RoundingMode.HALF_UP枚举替代。5.四舍五入方法优化// 原代码绕弯实现 BigDecimal one new BigDecimal(1); return b.divide(one, scale, BigDecimal.ROUND_HALF_UP).doubleValue(); // 优化后直接设置精度 return b.setScale(scale, RoundingMode.HALF_UP).doubleValue();原代码通过除以1来实现四舍五入虽然结果正确但逻辑不够直观。使用setScale()方法语义更清晰。6.参数校验增强// 新增除数为0的校验 private static void validateDivisor(double divisor) { if (divisor 0.0) { throw new ArithmeticException(除数不能为0); } } // 新增 NaN/Infinity 校验 if (Double.isNaN(value) || Double.isInfinite(value)) { throw new IllegalArgumentException(非法数值...); }7.异常信息中文化原代码使用英文异常信息优化后改为中文更符合国内团队开发习惯// 原代码 throw new IllegalArgumentException(The scale must be a positive integer or zero); // 优化后 throw new IllegalArgumentException(精度必须为非负整数当前值: scale); 使用示例public class Demo { public static void main(String[] args) { // 1. 加法 - 解决 0.1 0.2 ! 0.3 问题 double sum ArithTool.add(0.1, 0.2); System.out.println(0.1 0.2 sum); // 输出: 0.3 // 2. 减法 double diff ArithTool.subtract(1.0, 0.9); System.out.println(1.0 - 0.9 diff); // 输出: 0.1 // 3. 乘法 - 金额计算 double total ArithTool.multiply(19.99, 3); System.out.println(19.99 × 3 total); // 输出: 59.97 // 4. 除法 - 默认精度10位 double result1 ArithTool.divide(10, 3); System.out.println(10 ÷ 3 result1); // 输出: 3.3333333333 // 5. 除法 - 指定精度2位适合金额 double result2 ArithTool.divide(10, 3, 2); System.out.println(10 ÷ 3 (保留2位) result2); // 输出: 3.33 // 6. 四舍五入 double rounded ArithTool.round(3.14159, 2); System.out.println(3.14159 保留2位 rounded); // 输出: 3.14 } }⚡ 进阶建议如果需要支持更多数据类型当前工具类只支持double类型。实际业务中可能需要支持String、BigDecimal等类型可以扩展如下// 支持 String 类型避免 double 构造时的精度问题 public static double add(String v1, String v2) { BigDecimal b1 new BigDecimal(v1); BigDecimal b2 new BigDecimal(v2); return b1.add(b2).doubleValue(); } // 直接返回 BigDecimal避免转回 double 再次丢失精度 public static BigDecimal add(BigDecimal v1, BigDecimal v2) { return v1.add(v2); }如果用于金融系统金融计算建议全程使用BigDecimal最后一步才转换为double如果需要或者直接以BigDecimal返回// 金融场景推荐返回 BigDecimal避免多次类型转换 public static BigDecimal multiply(BigDecimal v1, BigDecimal v2) { return v1.multiply(v2); }

相关文章:

高精度运算工具类

高精度运算工具类(ArithTool)📖 背景:为什么要用高精度运算?在Java中使用 double 或 float 进行浮点数运算时,经常会遇到精度丢失的问题。这是因为计算机使用二进制存储浮点数,而某些十进制小数…...

快速上手StructBERT语义分析工具:中文句子匹配实战指南

快速上手StructBERT语义分析工具:中文句子匹配实战指南 1. 工具概览与核心价值 StructBERT语义分析工具是一款专为中文文本设计的本地化语义匹配解决方案。它基于阿里达摩院开源的StructBERT-Large模型,通过深度学习技术实现句子级别的语义相似度计算。…...

Intv_ai_mk11 本地开发环境搭建:WSL2 Ubuntu系统部署与调试全攻略

Intv_ai_mk11 本地开发环境搭建:WSL2 Ubuntu系统部署与调试全攻略 1. 为什么选择WSL2进行本地开发 对于Windows平台的开发者来说,直接在本地搭建AI开发环境往往会遇到各种兼容性问题。WSL2(Windows Subsystem for Linux)提供了一…...

AI教材编写秘诀大公开!低查重AI教材生成工具,高效创作不是梦

在编写教材的过程中,如何有效满足多样化的需求? 不同学段的学生在认知能力上存在显著差异,教材内容的深度需要谨慎把握,既不能过于深奥,也不能过于浅显。课堂教学和自主学习的场景各有不同,这要求教材的呈…...

AGV无线充电系统市场洞察:2026-2032年复合增长率(CAGR)为11.3%

据恒州诚思调研数据显示,2025年全球AGV无线充电系统市场规模达2.67亿元,预计到2032年将攀升至5.80亿元,2026-2032年复合增长率(CAGR)为11.3%。这一增长态势背后,是制造业、物流业对自动化、智能化物料搬运系…...

League Akari 助手:5大革新功能重塑你的英雄联盟游戏体验

League Akari 助手:5大革新功能重塑你的英雄联盟游戏体验 【免费下载链接】League-Toolkit An all-in-one toolkit for LeagueClient. Gathering power 🚀. 项目地址: https://gitcode.com/gh_mirrors/le/League-Toolkit 你是否曾在英雄选择阶段手…...

第11篇:从零搭建AUTOSAR开发环境:工具链选型与安装配置实战

为什么开发环境是AUTOSAR的第一道坎 很多工程师第一次接触AUTOSAR时,最直观的感受不是代码难写,而是“连环境都跑不起来”。AUTOSAR是一个极度依赖工具链的架构体系,传统的Makefile + GCC + JTAG三板斧在这里远远不够。你需要一套完整的商业工具或精心拼凑的开源方案,才能从…...

Unlock Music终极指南:如何免费解锁加密音乐文件,获得真正的音乐自由

Unlock Music终极指南:如何免费解锁加密音乐文件,获得真正的音乐自由 【免费下载链接】unlock-music 在浏览器中解锁加密的音乐文件。原仓库: 1. https://github.com/unlock-music/unlock-music ;2. https://git.unlock-music.dev…...

AGV/AMR锂电池市场调研:2026-2032年复合增长率(CAGR)将稳定在11.1%

据恒州诚思2024年Q2最新调研数据显示,全球AGV/AMR锂电池市场规模在2025年预计达5.38亿元,受仓储自动化、智能制造及智慧物流系统扩张驱动,2026-2032年复合增长率(CAGR)将稳定在11.1%,至2032年市场规模有望突…...

保姆级教程:用STM32F103C8T6的PWM驱动红外模块,实现格力空调万能遥控器

从零构建格力空调万能遥控器:基于STM32F103C8T6的PWM红外协议全解析 在智能家居DIY领域,红外遥控器改造一直是最具实用价值的入门项目之一。本文将带您完整实现一个能精准控制格力空调的STM32红外发射器,使用最常见的STM32F103C8T6开发板&…...

ArcGIS数据入库避坑指南:为什么你的BSM标识码总出错?3个常见问题解析

ArcGIS数据入库避坑指南:BSM标识码生成的3个致命陷阱与实战解决方案 自然资源数据入库就像给城市绘制数字身份证,而BSM标识码就是每块土地的"身份证号"。去年某省级国土调查项目中,37%的入库驳回案例都源于标识码错误——要么行政代…...

FPGA 外置Flash的读写,用户数据存储

FPGA 外置Flash的读写,用户数据存储前言一,该功能验证平台及参考文章1,Xilinx xc7k325tffg676-22,vivado 2017.43,验证的flash芯片:MT25QL2564,参考文章:MT25QL256_datasheet5&#…...

MCP23017 vs 74系列芯片:51单片机IO扩展方案对比与实战

MCP23017与74系列芯片:51单片机IO扩展方案深度解析与实战指南 当51单片机的GPIO资源捉襟见肘时,工程师们往往面临两种主流扩展方案的选择:传统的74系列逻辑芯片与现代化的MCP23017端口扩展器。这两种技术路线各具特色,适用于不同的…...

从IF控制到精准定位:Hall自学习如何重塑无感电机控制

1. 为什么我们需要Hall自学习技术 想象一下你正在组装一台电动滑板车。当你把电机装好准备测试时,发现转速总是不稳定,有时候还会突然卡顿。这种情况很可能就是由于电机内部的Hall传感器安装存在物理偏差导致的。传统电机控制模型假设三个Hall传感器之间…...

NumPy 中 transpose 详解

transpose 用于 NumPy 中高维度数组的轴变换,在二维情况下就是通常说的转置。该方法很不好理解,本文详细介绍该方法。 该方法有两个实现,分别是numpy.ndarray.transpose和numpy.transpose,两者分别是类成员方法和独立的方法&…...

FDTD仿真中PDMS光学参数txt文件的获取、验证与应用指南

1. PDMS光学参数在FDTD仿真中的重要性 做光学仿真的人都知道,材料参数准不准直接决定了仿真结果靠不靠谱。我刚开始用FDTD Solutions仿真PDMS微流控器件时,就吃过参数不准的亏——仿真结果和实验数据差了一大截,折腾了好几天才发现是折射率数…...

PPTist在线演示工具:5分钟快速制作专业幻灯片的完整指南

PPTist在线演示工具:5分钟快速制作专业幻灯片的完整指南 【免费下载链接】PPTist PowerPoint-ist(/pauəpɔintist/), An online presentation application that replicates most of the commonly used features of MS PowerPoint, allowing …...

【数据库】Redis的线程与IO

百万笔记知识库, 所有基础的笔记都在这里面啦,点击左边蓝字即可获取!助力每一位未来架构师! 欢迎大家在评论区唠嗑指正,觉得好的话别忘了一键三连哦!😘 文章目录线程模型通信流程文件事件处理器…...

《手把手教你评估二手车》林绪东 读书笔记

目录笔记一.事故车鉴定1.车漆2.缝隙及整车3.车身骨架笔记 一.事故车鉴定 事故车定义:存在结构性损伤的车辆,以及泡水、火烧车等。 不可通过拆卸螺丝更换的部件,多为结构件。 1.车漆 目的:1.车漆→车伤;2.车漆扣费 检…...

终极指南:如何免费解锁Cursor Pro全部功能,实现无限AI编程助手体验

终极指南:如何免费解锁Cursor Pro全部功能,实现无限AI编程助手体验 【免费下载链接】cursor-free-vip [Support 0.45](Multi Language 多语言)自动注册 Cursor Ai ,自动重置机器ID , 免费升级使用Pro 功能:…...

SAP PP实战:MRP Area怎么用?手把手教你按产线、委外供应商拆分物料计划

SAP PP实战:MRP Area精细化物料计划管理指南 引言 在制造业生产计划管理中,物料需求计划(MRP)的精确性直接影响着生产效率与成本控制。传统以工厂为单位的MRP运行模式往往难以应对复杂生产环境下的精细化需求——当多条产线并行运…...

Gold-YOLO:从论文到实践,深入剖析其高效目标检测的聚合-分发机制

1. 为什么需要Gold-YOLO的聚合-分发机制 目标检测领域有个经典难题:如何让模型同时看清远处的小目标和近处的大目标?这个问题困扰了研究者多年。传统解决方案FPN(特征金字塔网络)和PANet虽然在一定程度上缓解了多尺度检测的困难&a…...

上门做饭系统的数据可视化大屏:基于Echarts的实时业务监控与源码剖析

一、系统架构总览与业务背景1.1 上门做饭系统业务场景分析上门做饭系统是一种创新的O2O生活服务平台,连接专业厨师与有烹饪需求的用户。系统核心业务包括:用户端App(下单、支付、评价)、厨师端App(接单、路线规划、服务…...

【AI】《Autonomous Vehicles Learning Notes》

文章目录 1、自动驾驶简介 2、感知 传感器 多模态传感器融合 高精尖地图 BEV Occupancy Corner Cases 智能座舱芯片 3、End-to-end 4、Interesting Application 无头汽车 红绿灯检测 【附录】专业名词缩写 未完待续。。。 1、自动驾驶简介 来自:浅谈自动驾驶技术与挑战 L0:主…...

租了台RTX 4070服务器,终于跑通了NVIDIA Isaac Sim 4.2.0(附完整安装避坑指南)

云端RTX 4070实战:零基础部署NVIDIA Isaac Sim 4.2.0全流程实录 去年在机器人竞赛现场,当我那台搭载GTX 1660的笔记本在加载仿真环境时频频崩溃,才真正意识到高性能计算资源对AI机器人开发的决定性影响。这次经历促使我开始探索云端GPU解决方…...

UE4SS技术架构深度解析:从注入原理到虚幻引擎逆向工程完整解决方案

UE4SS技术架构深度解析:从注入原理到虚幻引擎逆向工程完整解决方案 【免费下载链接】RE-UE4SS Injectable LUA scripting system, SDK generator, live property editor and other dumping utilities for UE4/5 games 项目地址: https://gitcode.com/gh_mirrors/r…...

UART接收机设计:如何通过过采样策略提升波特率容错性

1. UART通信的波特率容差挑战 第一次用STM32做UART通信时,我遇到过这样的问题:明明发送端和接收端都设置了相同的115200波特率,但收到的数据总是出现乱码。后来用逻辑分析仪抓波形才发现,原来是两边的时钟源存在0.5%的偏差。这个经…...

实战教程:星图平台私有化部署Qwen3-VL:30B,实现本地AI多模态能力

实战教程:星图平台私有化部署Qwen3-VL:30B,实现本地AI多模态能力 1. 项目概述与准备工作 1.1 为什么选择Qwen3-VL:30B? Qwen3-VL:30B是目前最强大的开源多模态大模型之一,具备300亿参数规模,能够同时处理文本和图像…...

强化学习玩转目标检测:从决策建模到工业实战

1. 强化学习如何重新定义目标检测 传统的目标检测方法就像拿着放大镜在沙滩上找贝壳——你需要反复调整放大镜的位置和倍数,直到看清贝壳的轮廓。而强化学习则像训练一只聪明的海鸥,让它学会自己找到贝壳的最佳观察角度。这种范式转变让目标检测从"…...

FPGA图像采集卡设计笔记:为你的GigE Vision IP相机加个10G网口的升级攻略

FPGA图像采集卡10G网口升级实战:突破千兆带宽瓶颈的设计精要 当Basler相机的CMOS传感器分辨率从500万像素跃升至2000万,千兆以太网的传输带宽瞬间成为系统瓶颈。我曾亲眼见过一位工程师在调试4K60fps图像流时,千兆网口的数据指示灯疯狂闪烁&a…...