在网上一直流传着一个争论不休的话题:金额到底是用Long还是用BigDecimal?这个话题一出在哪都会引起异常无比激烈的讨论。。。。

比如说这个观点:算钱用BigDecimal是常识



有支持用Long的,将金额的单位设计为分,然后乘以100,使用Long进行存储以及计算,这样不用担心小数点问题。



并且一些银行系统就会选择用Long



还有,最最最牛逼的万能大法:用String



成年人不做选择题,Long跟BigDecimal都用。。。



还有一种就是封装一个金额的基类,对金额进行统一处理。

排除float和double

当然,对于金额,首先我们要排除的就是float和double。它们不适合用于精确的金融计算,因为floatdouble是基于IEEE 754标准的浮点数表示,它们无法精确地表示所有的十进制小数。这会导致在进行财务计算时出现舍入误差,这些误差可能会累积并导致不可预测的结果。

关于带精度的计算,我们不推荐使用float以及double,推荐使用BigDecimal,具体原因请参考:聊一聊_BigDecimal_使用时的陷阱

选择Long

Long类型在Java中用于存储64位整数。它的主要优点是速度快,因为整数运算在CPU层面是非常高效的。另外,Long类型也占用较少的内存,并且整数类型(BIGINT)在数据库中占用较少的存储空间。

但是Long类型在处理金额时有几个明显的缺点:

  1. 精度问题Long只能存储整数,无法直接表示小数。使用Long来表示以分为单位的金额(例如,100表示1元),此时就会失去小数的精度。即使使用某种方式来表示小数(例如,乘以100或10000),也会遇到舍入误差的问题。并且这种计算方式也会增加计算的复杂度。
  2. 浮点数问题:虽然这不是直接使用Long的问题,但如果你尝试将Long与浮点数(如doublefloat)进行转换以进行计算(比如汇率计算等),还是会遇到浮点数精度问题,这可能导致在财务计算中出现不可接受的误差。

在阿里巴巴的开发手册中建议使用Long。



但是在一些金融系统当中,对小数位要求比较高的,比如精确到小数点后6位,那么我们使用Long进行存储,每次在计算时都要除以或者乘以1000000,那么计算的开销就很大了。

并且,如果在需求确认时,我们无法知道金额要求的小数位,那我们使用Long也是不行的,我们并不知道需要乘以或者除以多少个0。

选择BigDecimal

BigDecimal是Java提供的一个类,用于任意精度的算术运算。它的主要优点是提供了高精度的计算,这对于金融和货币计算来说是非常重要的。BigDecimal可以表示任意大小的正数、负数或零,并可以精确控制舍入行为。并且在数据库中存储时也有对应的类型进行匹配,比如MySQL的DECIMAL类型提供了精确的数值存储,可以匹配BigDecimal的精度。

但是BigDecimal也有一些缺点:

  1. 性能:与Long相比,BigDecimal的性能较差。因为它的运算需要更多的内存和CPU时间。
  2. 复杂性:使用BigDecimal进行运算比使用Long或基本数据类型更复杂。你需要考虑舍入模式、精度等因素。
  3. 在数据库中需要更多的存储空间来存储小数部分。

而在Mysql的开发手册中,建议金额需要进行小数位计算时,存储要使用Decimal,否则我们要将金额乘以对应小数位的倍数变成BIGINT进行存储。

总结

基于上述对LongBigDecimal的优缺点分析,我们可以得出以下结论:

在金额计算层面,即代码实现中,推荐使用BigDecimal进行所有与金额相关的计算。BigDecimal提供了高精度的数值运算,能够确保金额计算的精确性,避免了因浮点数精度问题导致的财务误差。使用BigDecimal可以简化代码逻辑,减少因处理精度问题而引入的复杂性。

而在数据库存储方面,我们需要根据具体需求进行权衡。如果业务需求已经明确金额只需精确到分(如某些国家/地区的货币最小单位为分),并且我们确信不会涉及到需要更高精度的小数计算,那么可以使用Long类型进行存储,将金额转换为最小货币单位(如分)进行存储。这样可以节省存储空间并提高查询性能。

但是如果业务需求中金额的小数位数不确定,或者可能涉及多位小数的计算(如国际货币交易等),那么最好使用DECIMALNUMERIC类型进行存储。这些类型提供了精确的数值存储,可以确保数据库中的数据与应用程序中的BigDecimal对象保持一致,避免数据转换过程中可能引入的精度损失。

本文已收录于我的个人博客:码农Academy的博客,专注分享Java技术干货,包括Java基础、Spring Boot、Spring Cloud、Mysql、Redis、Elasticsearch、中间件、架构设计、面试题、程序员攻略等

争论不休的一个话题:金额到底是用Long还是BigDecimal?的更多相关文章

  1. 一个Java对象到底占用多大内存?

    最近在读<深入理解Java虚拟机>,对Java对象的内存布局有了进一步的认识,于是脑子里自然而然就有一个很普通的问题,就是一个Java对象到底占用多大内存? 在网上搜到了一篇博客讲的非常好 ...

  2. 一个Java对象到底占用多大内存

    在网上搜到了一篇博客讲的非常好,里面提供的这个类也非常实用: import java.lang.instrument.Instrumentation; import java.lang.reflect ...

  3. 一个Java对象到底占多大内存

    最近在读<深入理解Java虚拟机>,对Java对象的内存布局有了进一步的认识,于是脑子里自然而然就有一个很普通的问题,就是一个Java对象到底占用多大内存? 在网上搜到了一篇博客讲的非常好 ...

  4. 一个Java对象到底占多大内存?(转)

    最近在读<深入理解Java虚拟机>,对Java对象的内存布局有了进一步的认识,于是脑子里自然而然就有一个很普通的问题,就是一个Java对象到底占用多大内存? 在网上搜到了一篇博客讲的非常好 ...

  5. 【转】一个Java对象到底占多大内存?

    最近在读<深入理解Java虚拟机>,对Java对象的内存布局有了进一步的认识,于是脑子里自然而然就有一个很普通的问题,就是一个Java对象到底占用多大内存? 在网上搜到了一篇博客讲的非常好 ...

  6. 一个 Java 对象到底有多大?

    阅读本文大概需要 2.8 分钟. 出处:http://u6.gg/swLPg 编写 Java 代码的时候,大多数情况下,我们很少关注一个 Java 对象究竟有多大(占据多少内存),更多的是关注业务与逻 ...

  7. 输入一个url之后到底发生了什么 - Hurry

    背景 最近学习到 nginx 方向代理发现,nginx 可以将你的请求以 http 块的 server 形式代理到请求的域名或者 ip 地址. 一个简单的 nigx 配置如下: 12345678 se ...

  8. 一个 Java 字符串到底有多少个字符?

    来源:http://dwz.win/jqd 依照Java的文档, Java中的字符内部是以UTF-16编码方式表示的,最小值是 \u0000 (0),最大值是\uffff(65535), 也就是一个字 ...

  9. 【一起学源码-微服务】Nexflix Eureka 源码十:服务下线及实例摘除,一个client下线到底多久才会被其他实例感知?

    前言 前情回顾 上一讲我们讲了 client端向server端发送心跳检查,也是默认每30钟发送一次,server端接收后会更新注册表的一个时间戳属性,然后一次心跳(续约)也就完成了. 本讲目录 这一 ...

  10. 小程序中 radio 的一个坑,到底 checked 该赋什么值?

    https://blog.csdn.net/henryhu712/article/details/83059365

随机推荐

  1. 使用 Docker 部署 Answer 问答平台

    1)介绍 GitHub:https://github.com/apache/incubator-answer Answer 问答社区是在线平台,让用户提出问题并获得回答.用户可以发布问题并得到其他用户 ...

  2. WAF和IPS的区别

    简介 Web应用防火墙WAF(Web Application Firewall)和入侵防御系统IPS(Intrusion Prevention System)是网络安全领域中常见的两种安全解决方案,它 ...

  3. left jon连接查询踩坑记

    项目开发中经常会使用到多张表进行关联查询,比如left join关联查询. 如果有一张表A和一张表B,查询语句 SELECT a.*,b.name from A a left join B b On ...

  4. MFC自定义CStatusBar文字的颜色

    MFC里面的CStatusBar是没法自定义文字颜色的,需要我们自己绘制.这篇文章是在 Display colored text on Status Bar 代码的基础上进行改进的,使用起来更方便. ...

  5. 基于可穿戴的GPS定位存储模块方案特色解析

    前记   GPS作为一个位置定位手段,在日常生活中扮演着非常重要的角色.在研发动物可穿戴产品的同时.团队一直在做产品和模块标准化的事情,尽量把研发出来的东西标准化.按照任老板的说法,在追求理想主义的路 ...

  6. BES2300方案设计开发阶段总结

    前记   从事BES芯片的方案设计已经快三年了 ,这三年,伴随着和BES的一起共同成长,我们做了不少业内大的客户.从去年年初开始接触2300方案开发,到目前为止,已经做出了不少产品.这里就说一下心得体 ...

  7. 算法研究之快速排序java版

    很早之前就已经接触过快速排序算法了,面试当中也屡屡被问到,虽然明白其原理,但从未真正的用代码敲出来. 写关于算法的代码之前一定要原理想明白,不然就是盲目,在参考有关资料及自己的沉思之后,写出如下代码, ...

  8. 元宇宙解决方案——云端GPU在元宇宙中的作用

    GPU算力可以说是我们现在信息化时代的基础设施,在某种程度上说我们已经进入了算力时代,手机.电脑.车载等算力已经渗透到各行各业了. 当然算力对元宇宙也很重要,尤其是在可视化方面,元宇宙需要很逼真的渲染 ...

  9. FreeRTOS教程7 事件组

    1.准备材料 正点原子stm32f407探索者开发板V2.4 STM32CubeMX软件(Version 6.10.0) Keil µVision5 IDE(MDK-Arm) 野火DAP仿真器 XCO ...

  10. 三维模型OBJ格式轻量化压缩在大规模场景的加载和渲染的作用分析

    三维模型OBJ格式轻量化压缩在大规模场景的加载和渲染的作用分析 OBJ格式是一种常用的三维模型文件格式,它存储了三维模型的几何信息和纹理坐标等相关属性.在大规模场景中加载和渲染三维模型时,OBJ格式的 ...