一定要筆記
今天在使用某個成績系統時候遇到四捨五入結果與Excel的ROUND()比對有誤差的問題與負責的工程師一起測了一下之後發現造成此問題的原因是因為 .net 中 Math.Round() 函數的行為於是來與各位分享一下大家先猜猜下面四捨五入到小數第二位的輸出結果Math.Round(18.265, 2);Math.Round(18.265, 2, MidpointRounding.AwayFromZero);Math.Round(18.275, 2);Math.Round(18.275, 2, MidpointRounding.AwayFromZero);Math.Round(18.275M, 2);Math.Round(18.275M, 2, MidpointRounding.AwayFromZero);================================..答案分別是Math.Round(18.265, 2) = 18.26Math.Round(18.265, 2, AFZ) = 18.27Math.Round(18.275, 2) = 18.27Math.Round(18.275, 2, AFZ) = 18.27Math.Round(18.275M, 2) = 18.28Math.Round(18.275M, 2, AFZ) = 18.28而造成此原因是因Math.Round() 在遇到5的時候預設是使用 MidpointRounding.ToEven 作為捨去或進位的依據也就是會round到該位最近的偶數假設我需要四捨五入到小數第二位在遇到18.265的時候因為6是偶數,所以會做捨去如果18.265使用了MidpointRounding.AwayFromZero就會不管奇偶去做四捨五入得到與Excel的ROUND()相同的18.27但又有一個問題18.275出來為何都是18.27?這是因為在四捨五入過程中遇到了精度丟失造成了非預期的四捨五入行為改為decimal之後就正常了【結論】處理小數四捨五入的邏輯時#務必使用decimal型別#確認四捨五入邏輯#明確指定MidpointRounding模式才會得到精確的結果【補充】留言中有人有提到.net預設的 ToEven也就是 Banker's rounding兩種四捨五入設計給不同的用途開發前務必確認四捨五入的邏輯
沒有留言:
張貼留言