金额能不能用浮点数类型去存储? 核心结论一句话先记住计算机用二进制算十进制小数会“脑抽”像0.1、0.2这种简单的小数在计算机底层其实是无限循环小数。如果你图省事用float或double存钱算着算着钱就会悄悄蒸发或者凭空变多日终对账财务绝对会跟你拼命。 翻车现场浮点数算钱有多离谱我们直接看代码用事实说话。在 Java 中执行以下操作结果会让你怀疑人生publicclassFloatMoneyDemo{publicstaticvoidmain(String[]args){// 案例 10.1 0.2 居然不等于 0.3doublea0.1;doubleb0.2;System.out.println(0.1 0.2 (ab));// ❌ 实际输出: 0.30000000000000004System.out.println(ab0.3);// ❌ 输出: false// 案例 2每天存一毛钱存10天doubletotal0.0;for(inti0;i10;i){total0.1;}System.out.println(加了10次0.1: total);// ❌ 实际输出: 0.9999999999999999不是 1.0// 案例 3商品单价 19.9 元买 3 件doubleprice19.9;intcount3;System.out.println(19.9 * 3 (price*count));// ❌ 实际输出: 59.699999999999996}}原因其实很简单计算机用的是IEEE 754标准只有分母是 2 的幂次比如 0.5, 0.25的小数才能被精确转换成二进制。其他的数字都会被无情截断单次误差虽然小但大量累加或做乘除法时误差就会被无限放大。️ 正确的替代方案怎么抄作业在金融或者电商系统中正确的数钱姿势只有以下两种方式一使用BigDecimal官方高精度推荐 ⭐⭐⭐⭐⭐这是 Java 官方专门写出来应付高精度计算的“数学大师”。只要你用对了姿势它绝对不会错一分钱。⚠️死脑筋警告千万别用new BigDecimal(0.1)传入 double 的那一刻精度就已经脏了必须用字符串构造new BigDecimal(0.1)。 代码展示importjava.math.BigDecimal;importjava.math.RoundingMode;publicclassBigDecimalMoneyDemo{publicstaticvoidmain(String[]args){// ✅ 正确姿势必须使用字符串String构造BigDecimalanewBigDecimal(0.1);BigDecimalbnewBigDecimal(0.2);BigDecimalresulta.add(b);System.out.println(正确加法结果: result);// 输出: 0.3// ⚠️ 注意点 1比较大小要用 compareTo()绝对不能用 equals()// 因为 equals 会连带小数点后的位数精度一起比1.0 和 1.00 会返回 false。System.out.println(比较结果: (result.compareTo(newBigDecimal(0.3))0));// 输出: true// ⚠️ 注意点 2做乘除法时必须指定保留几位小数和“舍入模式”比如四舍五入// 否则遇到 10/3 这种除不尽的情况系统会直接抛出异常ArithmeticException卡死。BigDecimalpricenewBigDecimal(19.9);BigDecimalcountnewBigDecimal(3);// 算总价保留2位小数四舍五入BigDecimaltotalprice.multiply(count).setScale(2,RoundingMode.HALF_UP);System.out.println(正确的商品总价: total);// 输出: 59.70}}方式二把单位换成“分”全程用long高性能极客推荐 ⭐⭐⭐⭐既然小数不靠谱那我们直接把小数消灭掉1元100分。系统里所有的账目全部以“分”为单位存成整数long类型算完之后只有在展示给用户看的时候再除以 100 变成“元”。优势纯整数运算速度飞快内存占用极小。劣势不适合算利息这种需要超多小数位的复杂金融场景。 代码展示publicclassLongMoneyDemo{publicstaticvoidmain(String[]args){// 19.90 元在系统里直接存成 1990 分longpriceInCents1990;intcount3;// 全程整数乘法稳如老狗绝对不会丢失精度longtotalInCentspriceInCents*count;System.out.println(总价分: totalInCents);// 输出: 5970// 只有在最后页面展示、打印发票时再临时转成“元”doubletotalInYuantotalInCents/100.0;System.out.println(前端展示总价元: totalInYuan);// 输出: 59.7}}️ 数据库里面怎么存代码改好了数据库字段也别踩坑如果用方式一MySQL 字段类型请选择DECIMAL(19, 4)表示总共19位小数点后保留4位严禁使用 float/double。如果用方式二MySQL 字段类型请直接选择BIGINT直接存整数“分”。 终极秒记口诀浮点存金额精度必丢失BigD 用字符串除法指定舍或者用长整单位换成分