争议不断:金额到底是用Long还是BigDecimal?

先问个问题,在开发过程中你是选择用Long还是BigDecimal来处理金额?

浮点数陷阱

为什么排除float和double

浮点数无法精确表示许多十进制数。

图片

我们希望输出0.3,但由于浮点数的表示问题,实际结果却是0.30000000000000004,这在财务计算中是要命的。

Long的利与弊

Long对于不需要小数的场景,比如计数器、库存数量等,Long是理想的选择。

精度问题

先看个例子:

图片

Long为了表示小数,通常会乘以一个固定的基数(如100或10000),然后使用Long来存储。

上面的例子看起来没有问题,but 在处理更复杂的运算时,精度问题可能会显现。

比如下面这样,当涉及到除法或需要精确的舍入时:

 

java

public class LongPrecisionIssue {
public static void main(String[] args) {
// 表示100.05元和200.10元,转换为以分为单位的整数
long amount1 = 10005;
long amount2 = 20010;

// 除法运算(错误示例)
long result = amount2 / amount1;
System.out.println("Division Result: " + result); // 输出2,实际需要更精确的小数结果

// 舍入问题(错误示例)
long partialAmount = 3333; // 表示33.33元
long incorrectRounding = partialAmount / 3;
System.out.println("Incorrect Rounding: " + (incorrectRounding / 100.0)); // 输出11.11,而实际应为11.11~(更精确的结果)
}
}

Long适用于对精度要求不高且涉及大量整数运算的场景,比如计数、库存管理等。

但在涉及金融和需要精确小数的计算中,Long就显得力不从心了。

BigDecimal的高精度世界

BigDecimal提供了任意精度的运算能力,能够精确控制舍入行为,非常适合金融计算。

图片

舍入控制

BigDecimal允许我们精确控制舍入方式,例如HALF_UP(四舍五入),这在金融计算中尤为重要。

图片

缺点

尽管BigDecimal在精度和功能上优势明显,但它在性能和使用复杂性上有所牺牲。

因为每次运算都会创建新的BigDecimal对象,无形中增加了内存开销和GC压力。

实践案例

在实际开发中,还是建议使用BigDecimal来确保金额计算的精确性。

特别是在金融和电商等对金额精度要求高的场景中,BigDecimal几乎是必选项。

以下是一个简单的银行交易系统示例,展示如何使用BigDecimal进行精确的金额计算:

图片

第三方建议

阿里巴巴开发手册是建议使用Long来存储金额的整数部分,同时在应用层进行金额的格式化和计算,这种方法适用于业务逻辑较简单的场景。

MySQL官方推荐使用DECIMAL类型来存储金额,以确保存储和计算的精度,DECIMAL类型不仅可以表示精确的小数,还可以避免浮点数表示问题。

如果你的业务场景对金额的精度要求非常高,BigDecimal是首选;

如果是对整数金额进行处理,可以考虑使用Long。

最后说一句(求关注!别白嫖!)

如果这篇文章对您有所帮助,或者有所启发的话,求一键三连:点赞、转发、在看。

关注公众号:woniuxgg,在公众号中回复:笔记  就可以获得蜗牛为你精心准备的java实战语雀笔记,回复面试、开发手册、有超赞的粉丝福利!

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值