news 2026/4/22 19:33:23

BigDecimal除法异常:Non-terminating decimal expansion 解决方案

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
BigDecimal除法异常:Non-terminating decimal expansion 解决方案

问题描述

在使用BigDecimal进行精确计算时,特别是进行除法运算时,可能会遇到以下异常:

java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.

异常原因

BigDecimal是不可变的、任意精度的有符号十进制数,专为精确计算设计。但在除法运算中,当除不尽时(商是无限循环小数,如1除以3),如果没有指定舍入规则,BigDecimal无法精确表示结果,因此抛出此异常。

解决方案

方案1:使用divide()方法时指定舍入模式(推荐)

import java.math.BigDecimal; import java.math.RoundingMode; public class BigDecimalExample { public static void main(String[] args) { BigDecimal dividend = new BigDecimal("1"); BigDecimal divisor = new BigDecimal("3"); // 指定舍入模式(四舍五入,保留2位小数) BigDecimal result = dividend.divide(divisor, 2, RoundingMode.HALF_UP); System.out.println(result); // 输出: 0.33 // 其他舍入模式示例 // 向上取整 BigDecimal result2 = dividend.divide(divisor, 2, RoundingMode.UP); // 向下取整 BigDecimal result3 = dividend.divide(divisor, 2, RoundingMode.DOWN); // 银行家舍入法(四舍六入五成双) BigDecimal result4 = dividend.divide(divisor, 2, RoundingMode.HALF_EVEN); } }

方案2:使用MathContext指定精度

import java.math.BigDecimal; import java.math.MathContext; import java.math.RoundingMode; public class BigDecimalExample2 { public static void main(String[] args) { BigDecimal dividend = new BigDecimal("1"); BigDecimal divisor = new BigDecimal("3"); // 使用MathContext指定精度和舍入模式 MathContext mc = new MathContext(4, RoundingMode.HALF_UP); BigDecimal result = dividend.divide(divisor, mc); System.out.println(result); // 输出: 0.3333 } }

常用舍入模式详解

舍入模式描述示例(保留0位小数)
RoundingMode.UP远离零方向舍入2.5 → 3, -2.5 → -3
RoundingMode.DOWN向零方向舍入2.5 → 2, -2.5 → -2
RoundingMode.CEILING向正无穷方向舍入2.5 → 3, -2.5 → -2
RoundingMode.FLOOR向负无穷方向舍入2.5 → 2, -2.5 → -3
RoundingMode.HALF_UP四舍五入2.5 → 3, -2.5 → -3
RoundingMode.HALF_DOWN五舍六入2.5 → 2, 2.6 → 3
RoundingMode.HALF_EVEN银行家舍入法2.5 → 2, 3.5 → 4

实际业务场景选择建议

1. 金融计算(金额处理)

// 金额计算通常需要保留2位小数,使用四舍五入 BigDecimal amount = price.divide(quantity, 2, RoundingMode.HALF_UP);

2. 科学计算

// 科学计算可能需要更高精度 BigDecimal result = value1.divide(value2, 10, RoundingMode.HALF_UP);

3. 比例计算

// 百分比计算,保留4位小数 BigDecimal percentage = part.divide(total, 4, RoundingMode.HALF_UP) .multiply(new BigDecimal("100"));

最佳实践

  1. 始终在除法运算中指定舍入模式,避免潜在的异常

  2. 根据业务需求选择合适的精度和舍入模式

  3. 金额计算统一使用2位小数精度

  4. 使用字符串构造函数创建BigDecimal,避免精度丢失

// 推荐 BigDecimal d1 = new BigDecimal("0.1"); // 不推荐(可能丢失精度) BigDecimal d2 = new BigDecimal(0.1);

工具类示例

import java.math.BigDecimal; import java.math.RoundingMode; public class BigDecimalUtils { // 默认金融计算精度(2位小数) private static final int DEFAULT_SCALE = 2; /** * 安全的除法运算(使用默认精度和四舍五入) */ public static BigDecimal safeDivide(BigDecimal dividend, BigDecimal divisor) { if (divisor.compareTo(BigDecimal.ZERO) == 0) { throw new ArithmeticException("除数不能为零"); } return dividend.divide(divisor, DEFAULT_SCALE, RoundingMode.HALF_UP); } /** * 安全的除法运算(自定义精度和舍入模式) */ public static BigDecimal safeDivide(BigDecimal dividend, BigDecimal divisor, int scale, RoundingMode roundingMode) { if (divisor.compareTo(BigDecimal.ZERO) == 0) { throw new ArithmeticException("除数不能为零"); } return dividend.divide(divisor, scale, roundingMode); } /** * 百分比计算 */ public static BigDecimal calculatePercentage(BigDecimal part, BigDecimal total) { BigDecimal ratio = safeDivide(part, total, 4, RoundingMode.HALF_UP); return ratio.multiply(new BigDecimal("100")); } }

总结

Non-terminating decimal expansion异常的根本原因是BigDecimal除法运算中无限小数的存在。解决此问题的关键在于:

  1. 必须在调用divide()方法时指定精度和舍入模式

  2. 根据业务场景选择合适的舍入策略

  3. 金融计算通常使用HALF_UP(四舍五入)模式

  4. 建议封装工具类统一处理BigDecimal运算

遵循这些原则,可以确保BigDecimal计算的精确性和稳定性,避免运行时异常的发生。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/16 6:50:27

AnimeGANv2模型蒸馏实验:进一步压缩体积可行性

AnimeGANv2模型蒸馏实验:进一步压缩体积可行性 1. 引言 1.1 AI二次元转换器的轻量化需求 随着AI模型在移动端和边缘设备上的广泛应用,模型体积与推理效率成为决定用户体验的关键因素。AnimeGANv2作为一款广受欢迎的照片转动漫风格迁移模型&#xff0c…

作者头像 李华
网站建设 2026/4/19 10:09:59

AnimeGANv2部署案例:动漫风格在教育课件中的应用

AnimeGANv2部署案例:动漫风格在教育课件中的应用 1. 引言 随着人工智能技术的不断演进,AI驱动的图像风格迁移正逐步从娱乐场景向教育、设计等实用领域渗透。在众多轻量级风格迁移模型中,AnimeGANv2 因其出色的二次元风格转换能力与高效的推…

作者头像 李华
网站建设 2026/4/16 9:18:17

企业内网部署Google镜像站点的完整解决方案

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容: 请生成一个企业内网可用的Google镜像站点后端服务代码,要求:1. 使用Python Flask框架实现代理服务;2. 能够转发搜索请求到真实的Google服务器&a…

作者头像 李华
网站建设 2026/4/19 18:22:19

对比测试:传统JVM排查 vs 基于JVISUALVM的标准化流程

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容: 开发一个效率对比测试工具,功能包括:1.自动生成标准化的JVM问题场景(内存泄漏/线程死锁等)2.记录传统方法(日志分析手动…

作者头像 李华
网站建设 2026/4/17 16:27:51

办公效率翻倍:智能扫描仪镜像处理合同文件全流程

办公效率翻倍:智能扫描仪镜像处理合同文件全流程 在现代办公场景中,纸质合同、发票、证件等文档的电子化已成为日常刚需。传统扫描设备操作繁琐,而手机拍照又存在角度倾斜、阴影干扰、背景杂乱等问题,严重影响后续归档与OCR识别效…

作者头像 李华
网站建设 2026/4/16 20:34:30

低成本体验AI黑科技:MediaPipe Holistic 1元试用攻略

低成本体验AI黑科技:MediaPipe Holistic 1元试用攻略 1. 什么是MediaPipe Holistic? MediaPipe Holistic是谷歌开发的一款开源AI工具包,它能同时检测人体的面部表情、手势动作和身体姿态。简单来说,就像给你的电脑装上了一双&qu…

作者头像 李华