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