You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java 11中BigDecimal转double计算丢失精度问题求助

问题描述

使用Java 11与IntelliJ IDEA开发,从外部系统获取字符串格式的价格数据,当前通过以下代码提取售价:

BigDecimal sellingPrice = BigDecimal.valueOf(Double.parseDouble(somesalesprice));

调试显示sellingPrice的值为"4.350000000",但执行以下代码转换时:

long roundedSellingPrice = (long) (sellingPrice.doubleValue() * 100);

结果为"434",莫名丢失1分。在500+条数据中约有40条出现该问题,且均为少1分,无法找到这些数据的共性,求问题原因。

问题原因与解决方案

核心原因:浮点数精度丢失

  • Double类型的固有缺陷:Double.parseDouble(somesalesprice)会把字符串转成double类型,但double是二进制浮点数,无法精确表示所有十进制小数(比如4.35)。实际存储的是一个接近4.35但略小于它的值(比如4.3499999999999996)。
  • BigDecimal.valueOf(double)的局限性:你用BigDecimal.valueOf(double)把这个不精确的double转成BigDecimal,虽然调试显示为"4.350000000",但这只是BigDecimal的格式化显示,底层实际存储的还是那个略小的近似值。
  • 强制类型转换的截断:当调用sellingPrice.doubleValue()时,又回到了那个略小于4.35的double值,乘以100后得到的是434.99999999999994,强制转成long时会直接截断小数部分,得到434。

正确解决方案

直接用BigDecimal的字符串构造方法,跳过double转换的步骤,从根源避免精度问题:

// 直接用字符串构造BigDecimal,保留精确的十进制值
BigDecimal sellingPrice = new BigDecimal(somesalesprice);
// 使用BigDecimal的精确运算来转成分
long roundedSellingPrice = sellingPrice.multiply(new BigDecimal("100")).longValue();

或者结合缩放规则做更严谨的处理:

long roundedSellingPrice = sellingPrice.setScale(2, RoundingMode.HALF_UP)
                                     .multiply(new BigDecimal(100))
                                     .longValue();

内容的提问来源于stack exchange,提问作者JustLudo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 20:45:27