技术

保留小数导致的金额异常

什么地方发生的金额缺失

今日在写完WQ的工作量报表生成,在比对数据时发现数据存在偏差,但并不是很大的偏差,而是只有几块钱的偏差,一开始一直在检查是不是公式错误,导致数据错误,在Excel中操作了半天,结果好像没找到有什么公式上的错误,就开始检查数据为什么不一致,发现是因为除数太小导致精度损失的问题

为什么会发生金额缺失

举个例子,现有B、C公司,两公司2023年待发奖金为345.67万元,B公司人均产出529元,C公司人均产出250元(举例)。将这部分奖金按B公司和C公司的人均产出金额比例分配到B公司和C公司。

实际情况,B公司应该分配到345.67*529/(529+250)=234.74万元,C公司应该分到345.67*250/(529+250)=110.93万元。

在代码中计算时,这里举一个例子

  1. 首先算出权重,然后以权重✖️总待分配金额,这个时候权重的取值会出现多种情况
    • 权重是计算好的,已经丢失精度(仅保留2位小数),
      • B:529/(529+250)=0.68,C:250/(529+250)=0.32
      • B公司分到345.67*0.68约等于235.06万元
      • C公司分到345.67*0.32约等于110.61万元
    • (准确)权重是实时计算的,且保留多位小数
      • B:0.6790757381,C:0.3209242619
      • B公司分到345.67*0.6790757381=234.736110389万元约等于234.74万元
      • C公司分到345.67*0.3209242619=110.933889611万元约等于110.93万元

金额精度缺失的原因

  • (直接原因)获取数据的精度缺失
    • 仅从此处来看,如果获取到了一个精度缺失的数据
  • (根本原因)保留数据的精度不对
    • 作为一个需要高精度的数字,实际上仅保留了2位小数,这会直接导致金额出现错误。

如何避免这种问题

在代码层面,在进行除法时,需要判断除数是否能完整表示,若不能,则尽可能保证除数的精度

在数据库层面,数据库最好保留高精度数字,而不是根据页面需要显示几位数字直接在数据库进行保留,这样会导致精度丢失,可能会影响后续的计算结果

在架构层面,我认为数据计算方应保证数据精度的准确性,即不进行保留小数操作。若一定要保留小数,则该一步里最终渲染数据越近越好