浮点数类型导致金额计算错误复盘总结

📌 业务场景 公司通过爬虫获取界面上的商品价格(例如 2.01 元),需要将其转换为以 分为单位的整数 (即 201)存储到数据库中。 后端接收价格时为 String 类型,最终需转换为 Integer 类型存入数据库。

⚠️ 问题再现 直接使用 Double 转换会因浮点数精度问题导致计算错误:

ini 复制代码
String money = "2.01";
// ❌ 错误示范:使用Double处理金额
Double esMoney = Double.valueOf(money);
System.out.println(esMoney);  // 打印:2.01(表面显示正常)
Double v = esMoney * 100;
System.out.println(v); // 打印:200.99999999999997(误差被放大)
int moneyInt = new Double(esMoney * 100).intValue();
System.out.println(moneyInt); // 最终错误结果:200(正确应为201)

🔍 问题原因 Double 采用二进制存储数据,部分十进制小数(如 2.01)无法被精确表示,只能存储近似值。 当进行乘法运算(如 ×100)时,微小的误差会被放大,导致最终结果出错。

正确解决方案 使用 BigDecimal 处理金额计算(底层基于十进制运算,无精度损失):

ini 复制代码
String money = "2.01";
// ✅ 正确示范:使用BigDecimal处理金额
BigDecimal bigDecimal = new BigDecimal(money); // 注意:必须用String构造,而非double
int moneyInt2 = bigDecimal.multiply(new BigDecimal(100)).intValue();
System.out.println(moneyInt2); // 正确结果:201

📝 核心总结

  1. 处理 金额、高精度浮点数 时,务必使用 BigDecimal 而非 Double/Float
  2. 初始化 BigDecimal 时,必须传入 String 类型参数(避免因 double 本身的精度问题引入误差)。

💻 完整测试代码

ini 复制代码
public static void main(String[] args) {
    String money = "2.01";
    
    // ❌ 错误示范
    Double esMoney = Double.valueOf(money);
    System.out.println(esMoney);  // 2.01
    Double v = esMoney * 100;
    System.out.println(v); // 200.99999999999997
    int moneyInt = new Double(esMoney * 100).intValue();
    System.out.println(moneyInt); // 200
    
    // ✅ 正确示范
    BigDecimal bigDecimal = new BigDecimal(money);
    int moneyInt2 = bigDecimal.multiply(new BigDecimal(100)).intValue();
    System.out.println(moneyInt2); // 201
}
相关推荐
毕设源码-郭学长1 天前
【开题答辩全过程】以 基于springboot 的豪华婚车租赁系统的设计与实现为例,包含答辩的问题和答案
java·spring boot·后端
Loo国昌1 天前
深入理解 FastAPI:Python高性能API框架的完整指南
开发语言·人工智能·后端·python·langchain·fastapi
码农水水1 天前
米哈游Java面试被问:机器学习模型的在线服务和A/B测试
java·开发语言·数据库·spring boot·后端·机器学习·word
计算机学姐1 天前
基于SpringBoot的美食分享交流平台
java·spring boot·后端·spring·java-ee·intellij-idea·美食
源代码•宸1 天前
Leetcode—746. 使用最小花费爬楼梯【简单】
后端·算法·leetcode·职场和发展·golang·记忆化搜索·动规
毕设源码-朱学姐1 天前
【开题答辩全过程】以 基于Django框架中山社区社会补助系统为例,包含答辩的问题和答案
后端·python·django
J_liaty1 天前
分库分表深度解析
后端
AIFQuant1 天前
如何通过股票数据 API 计算 RSI、MACD 与移动平均线MA
大数据·后端·python·金融·restful
x70x801 天前
Go中nil的使用
开发语言·后端·golang
REDcker1 天前
libwebsockets库原理详解
c++·后端·websocket·libwebsockets