java在银行业务数值金额计算问题处理篇
java在银行业务数值金额计算问题处理篇
介绍
在Java中处理银行相关的精度问题,尤其是货币计算时,浮点型(float
/double
)的精度缺失会导致严重问题
为什么不能用 double
或 float
表示金额?
因为double和
float无法精确表示十进制小数(如 0.1
)
System.out.println(0.1 + 0.2); // 输出 0.30000000000000004
如何精确处理金额精度问题
1、用**BigDecimal
**类
- 支持任意精度的十进制运算。
- 必须用
String
构造器(避免double
传参的误差):
BigDecimal a = new BigDecimal("0.1");
BigDecimal b = new BigDecimal("0.2");
BigDecimal sum = a.add(b); // 精确等于 0.3
// 会传递 double 的不精确值(实际为 0.100000000000000005551...)
BigDecimal a = new BigDecimal(0.1); // 使用 double 构造
除法需指定舍入模式(如 RoundingMode.HALF_UP
):
BigDecimal result = a.divide(b, 2, RoundingMode.HALF_UP); // 保留两位小数
2、整数表示法
以 最小货币单位(如分)存储金额(long
类型)
- 示例:存储
1.25 元
→125 分
。 - 优点:避免浮点数问题,计算高效。
3、如何解决BigDecimal性能差问题
在高频交易系统中,BigDecimal
性能较差。可以用用 long
表示分,如 1元 = 100分
。若需要进行除法运算,可以自己写工具类取模,求余数等进行四舍五入计算。
如何正确比较金额大小
1、正确比较两个 BigDecimal
对象
推荐使用**compareTo()
**,仅比较数值
new BigDecimal("2.0").compareTo(new BigDecimal("2.00")) == 0 // true
不推荐**equals()
**,它会严格比较值和精度(scale
)
new BigDecimal("2.0").equals(new BigDecimal("2.00")) // false(精度不同)
数据库存储金额方案
1、使用字段类型为**DECIMAL(p, s)
** 类型
如 DECIMAL(15, 2)
,15
:总位数(整数+小数),2
:小数位数。