2022年7月14日 星期四

[BigDecimal] 關於五捨六入的誤解

其實這不算BigDecimal的問題,而是我們在認知上的錯誤

今天跑完加班費批次,人資跟我提到每次計算出來的加班費都會多個幾塊錢,
花了些時間比對雙方計算的結果,才發現原來是BigDecimal五捨六入的問題。
//五捨六入
BigDecimal overtimePay = bigDecimal.setScale(0, RoundingMode.HALF_DOWN);

在網路上找BigDecimal的進位方式都可以看到以下的說法
RoundingMode.HALF_UP    //四捨五入
RoundingMode.HALF_DOWN  //五捨六入

一般我們認知的進位,會是以下的結果

//四捨五入到整數位
19.4   -> 19  //正確
19.41  -> 19  //正確
19.52  -> 20  //正確
//五捨六入整數位,理所當然會把四捨五入的概念拿來套用
19.4   -> 19  //正確
19.41  -> 19  //正確
19.52  -> 19  //感覺5應該要捨去,但實際跑過才發現進位了,答案是20

仔細看了BigDecimal的註解,才發現他的運作是這樣

將待進位的區塊分成兩等份,待捨棄的部分若坐落於左半邊則直接捨去,落於右半邊則進位。
而HALF_UP跟HALF_DOWN只控制剛好落在正中間½時的處理,前者保留,後者捨去。

因此19.52使用HALF_DOWN取到整數位時,
待捨去的部分的0.52,落於小數點後的右半邊區塊,故結果才會是進位。








和人資討論了這結果,他表示希望改成他認知中的五捨六入。
因此最後是將小數第二位以後直接刪掉,再對其進行HALF_DOWN,即是人資要的答案了。



沒有留言:

張貼留言