java项目中与金额有关的计算注意事项

java项目中与金额有关的计算注意事项

前言:

在项目中,财务相关的数据计算可能会通过项目进行各种计算以及存库,本篇讲述这个过程中的注意事项。

1.浮点型的误差

浮点型由于其定义的原因,在使用的时候总会存在误差,以下以pgsql为例:

sql 复制代码
select 0.1::float+0.2::float; -- 返回结果:0.30000000000000004

可以看到这就出现了误差,尾数末尾有个4,在计算中进行比较的时候可能就会出现错误,比如0.1+0.2 > 0.3了。

所以在项目中与金额有关的计算全部避免使用浮点型,像java中的double,float以及对应的封装类,pgsql中的float等,均避免使用。

2.数据库中如何存储

第一小节讲述了浮点型可能造成的误差,那么数据库中应该如何存储呢,以pgsql为例,应当使用decimal或者numeric存储,这种类型的固定精度和标度的数值可以避免浮点数误差导致的问题。

3.java中如何避免浮点精度问题

java中有一个BigDecimal类,与pgsql中decimal和numeric类似,都是固定精度和标度的数值,都不会有浮点型的误差,但是需要注意的是,在使用的时候不能使用Double接收了前端参数之后,再由这个double类型初始化BigDecimal,从前端接受和后端取库中数据以及计算,应当全程使用BigDecimal,避免中间任意一环使用浮点数。

4.其他案例

在避免了浮点数精度导致的问题的时候,金额计算可能会伴随着其他问题,下面进行举例:

以一个简单的奖金计算为例,一个项目有若干个里程碑,每个里程碑有对应的进度,里程碑达成后,会生成里程碑进度×项目金额的奖金,由于金额的最小单位是分,所以数据库中存储保留两位小数并且去除多余尾数的时候向下取整。假设项目金额10000.57,有两个里程碑,第一个里程碑进度33%,第二个里程碑进度67%,总和为100%。

当第一个里程碑达成的时候,获得的奖金为10000.57×0.33=3,300.1881,保留两位小数后获得结果3,300.18,第二个里程碑达成后获取奖金10000.57×0.67=6,700.3819,保留两位小数取得结果6700.38,两次奖金相加3300.18+6700.38=10000.56,总的奖金生成少了1分钱,这一分钱看似无所谓,财务计算的时候能要命。

  • 那么应该如何避免呢?
    • 首先这个问题是怎么造成的呢?这个问题是因为进行了保留小数的操作,造成的,那么就有两种方案:
      • 不舍去多余小数。(但是如果一定要舍去的情况咋办呢qwq,其实讲这个案例就是为了说明保留小数位数后造成最后总金额算出来不对)
      • 在某个环节补回来,上面这个案例就可以在最后一个里程碑达成之后,和总奖金进行计算,将误差的金额补回来。

5.总结

  • 数据库存储金额的时候避免使用浮点数,以pgsql为例,使用numeric或者decimal。
  • java中避免浮点数精度问题的时候,从接受前端数据到后端存库以及中间计算,全程使用BigDecimal接受前端参数和进行运算以及存库。
  • 金额相关的计算都应该慎重考虑,不止浮点数造成的误差,保留小数位数的操作可能也会造成误差,需要在某些环节补回来。
    最后欢迎各位大佬批评指正QWQ
相关推荐
金銀銅鐵4 小时前
带您看懂字节码指令(一):一帧里有什么
java·后端·ai编程
nice_lcj5206 小时前
【从零理解 Spring AI · 14】RAG 的四个环节:加载、切分、向量化、检索
java·spring boot·embedding·向量数据库·rag·spring ai·ai应用开发
SomeOtherTime7 小时前
Rust所有权(AI回答)
开发语言·后端·rust
Easyhood7 小时前
Android 开发入门实践(十四):Compose 副作用入门与四个常用 API
android·开发语言·kotlin·android jetpack·compose
白杨尚青8 小时前
C++进阶篇(六):map 和 set 的模拟实现——用红黑树封装 mymap/myset(迭代器 + operator[])
开发语言·c++·迭代器·stl·set·map·红黑树
学长毕设8 小时前
基于springboot科创竞赛信息平台-附源码
java·spring boot·后端
聪明的笨猪猪8 小时前
Java 工程案例:AI 生成 @Async 异步线程池踩坑
java·经验分享·面试·ai编程
学长毕设9 小时前
基于SpringBoot公务员考试交流平台-附源码
java·spring boot·后端
SL_staff11 小时前
私有化低代码:面向强监管行业的可控数字化实践
java·低代码
饮水桶_T11 小时前
JAVA IO流笔记
开发语言·数据结构·算法