2026/4/18 17:10:42
网站建设
项目流程
网站结构物理,网站和手机网站,怎么提交公司网站,wordpress tag 链接问题描述在使用BigDecimal进行精确计算时#xff0c;特别是进行除法运算时#xff0c;可能会遇到以下异常#xff1a;java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.异常原因BigDecimal是不可变的、任意精度的…问题描述在使用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 → -3RoundingMode.DOWN向零方向舍入2.5 → 2, -2.5 → -2RoundingMode.CEILING向正无穷方向舍入2.5 → 3, -2.5 → -2RoundingMode.FLOOR向负无穷方向舍入2.5 → 2, -2.5 → -3RoundingMode.HALF_UP四舍五入2.5 → 3, -2.5 → -3RoundingMode.HALF_DOWN五舍六入2.5 → 2, 2.6 → 3RoundingMode.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));最佳实践始终在除法运算中指定舍入模式避免潜在的异常根据业务需求选择合适的精度和舍入模式金额计算统一使用2位小数精度使用字符串构造函数创建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除法运算中无限小数的存在。解决此问题的关键在于必须在调用divide()方法时指定精度和舍入模式根据业务场景选择合适的舍入策略金融计算通常使用HALF_UP四舍五入模式建议封装工具类统一处理BigDecimal运算遵循这些原则可以确保BigDecimal计算的精确性和稳定性避免运行时异常的发生。