兩個層面,解決結算(財務)系統小數精度問題
本文筆者將從兩個層面,講述:在做財務系統時遇到的關于小數精度的問題,該如何解決?
最近在做財務系統中遇到一個關于小數精度的問題:
我們知道計算機在訂單結算信息的時候,是通過單條訂單計算結算金額,然后整體匯總再給出結果。這樣才能支持業務上需要從不同時間維度匯總數據的要求(每3天一結算,每7天一結算,每月一結算等)。但是,作為一個正常用戶,我們并不會這么去計算,我們采用的是先匯總商品價格再計算結算金額的方法,如下方展示:
結算公式: 應結算金額 = 商品價格-商品價格*傭金比例
計算機: 計算訂單1的應結算金額J1,計算訂單2的應結算金額J2,計算訂單3的應結算金額J3,然后匯總。
人工計算:計算訂單1,訂單2,訂單3的商品價格匯總,再按照總的商品價格計算應結算金額。
我們剛開始對計算機計算的每一個J1,J2,J3都采取四舍五入的方法,發現最后和人工核對時算出的結果是不一樣的,會有精度上的誤差。計算機匯總的結果可能是4.56,而人工算的是4.57,那么怎么辦呢?
要從兩個層面解決這個問題
1. 系統層面
- 改造計算系統的規則,舍棄2位小時的方式改為采用4位小數的方式計算具體金額。
- 更改數據修約的規則,舍棄四舍五入的方法,改為采用四舍六入五成雙法,關于四舍六入五成雙法在后面給出說明。
2. 展現層面
- 在后臺展現4位精度。
- 在用戶余額等和外部系統有資金交互的地方只展示2位小數,采用向下取整的方法(4.5667取4.56)保證系統不會多付錢給用戶。
通過以上方法,我們保證了整個財務系統精度符合業務要求,能夠正常運作。
四舍六入五成雙法
1. 含義
對于位數很多的近似數,當有效位數確定后,其后面多余的數字應該舍去,只保留有效數字最末一位。這種修約(舍入)規則是“四舍六入五成雙”,也即“4舍6入5湊偶”。
這里“四”是指≤4 時舍去,”六”是指≥6時進上,”五”指的是根據5后面的數字來定,當5后有數時,舍5入1;當5后無有效數字時,需要分兩種情況來講:
- 5前為奇數,舍5入1;
- 5前為偶數,舍5不進(0是偶數)。
2. 為什么要這樣做?
從統計學的角度,“四舍六入五成雙”比“四舍五入”要科學,在大量運算時,它使舍入后的結果誤差的均值趨于零,而不是像四舍五入那樣逢五就入,導致結果偏向大數,使得誤差產生積累進而產生系統誤差,“四舍六入五成雙”使測量結果受到舍入誤差的影響降到最低。
本文由@shinian 原創發布于人人都是產品經理,未經許可,禁止轉載
題圖來自Unsplash, 基于CC0協議
這種情況一般通知公司的技術人員,這是技術人員代碼的bug。在Java里一般價格是long類型的但是在頁面顯示是double類型的,價格從double轉為long會損失精度,但是代碼是能修復這種bug的。
您好,看了您的文章很有收獲,可以加微信進一步溝通嗎,我的微信號15933556182
你好,是余額會保留4位小數嗎,還是分別保存4位和2位兩種,如果保存4位,對賬及平衡檢查會對不上吧。這塊怎么處理
好硬核,用處不大
感覺用處不大,遇到5的情況很少,問題還是沒解決
不用了,百度百科里找到了
5湊偶那還是有點不明白,能拿幾個數舉例嗎?