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
相关推荐
蛋蛋的就会顺顺的2 小时前
hot100 p0——栈,贪心算法,动态规划
java·前端·javascript·算法·leetcode·力扣
余槐i2 小时前
PostgreSQL 函数索引报错 must be immutable:3种绕法与代价
数据库·后端·sql·postgresql·性能优化
数据库小学妹2 小时前
PostgreSQL表膨胀怎么办?autovacuum清不动的根因与排查命令
数据库·postgresql·表膨胀·mvcc·数据库运维
需要8263 小时前
Spring Bean 生命周期:从实例化到销毁的完整钩子
java·后端·spring
小 黄 鸡3 小时前
HashMap 面试必会知识点详解(JDK 8)
java·面试·职场和发展
死磕音视频3 小时前
让小模型做选择题:限定候选项并读取 logits 概率的入门实践(附 Python 代码)
开发语言·python·大模型·文本分类·transformers
凤山老林4 小时前
Spring Boot 接入国密 SM2/SM3/SM4 的一些实践记录
spring boot·后端·python
伯恩bourne5 小时前
Spring Boot Bean 注册的两种方式:@Component 家族 vs @Configuration + @Bean
java·spring boot·后端
silvamux_5 小时前
curl 测试 OpenAI 兼容 API 的完整流程
java·人工智能·缓存·ai·oneapi
省钱兄--zs5 小时前
深圳24小时自助健身房软硬件解决方案实战指南与开发流程详解
java·数据仓库·spring boot·小程序·架构