javaScript 中 toFixed() 精度問題及解決方案

昨天工作中發(fā)現(xiàn)了一個問題,是后端計算的成交價和前端計算的成交價有時候會有一分錢的差異,后來發(fā)現(xiàn)是由于 toFixed 的方法存在差異。

在 C# 中的取舍方法使用的是銀行家舍入法,也就是四舍六入五取偶(又稱四舍六入五留雙)。在 javaScript 中 Number.prototype.toFixed()的方法在四舍和六入上沒什么爭議,而當判斷位為5的時候就顯得有點奇怪。

銀行家舍入法

據(jù)說,大部分的編程軟件都使用的是這種方法,也算是一種國際標準。 所謂銀行家舍入法,其實質是一種四舍六入五取偶(又稱四舍六入五留雙)法。其規(guī)則是:當舍去位的數(shù)值小于5時,直接舍去該位;當舍去位的數(shù)值大于等于6時,在舍去該位的同時向前位進一;當舍去位的數(shù)值等于5時,如果前位數(shù)值為奇,則在舍去該位的同時向前位進一,如果前位數(shù)值為偶,則直接舍去該位。

以下是各個瀏覽器中測試 toFixed() 的結果:

Chrome:

Chrome 下的 toFixed

FireFox:

FF 下的 toFixed

IE:

IE 下的 toFixed

可以看出在不同瀏覽器中,toFixed方法都給出了不同的結果,讓人摸不到頭腦。

于是我查詢了 ECMA 里Number.prototype.toFixed() 的規(guī)范,如下:

?ECMA-262?Number.prototype.toFixed()

拿 0.15 和 10.15 舉個栗子。

(0.15).toFixed(1)

num = 0.15; f = 1;

根據(jù)步驟 10.a :

2 ÷ 10^f - num? ? ? ? // 0.05000000000000002

1 ÷?10^f - num? ? ? ? // -0.04999999999999999

取最接近 0 的值,得 (0.15).toFixed(1) 返回 0.1。

(10.15).toFixed(1)

num = 10.15; f = 1;

根據(jù)步驟 10.a :

102 ÷?10^f - num? ? ? ? //? 0.049999999999998934

101 ÷?10^f - num? ? ? ? //?-0.05000000000000071

取最接近 0 的值,得 (10.15).toFixed(1) 返回 10.2。

歸根到底就是浮點數(shù)精度的鍋。


找到原因后,我想到了兩種解決方案:

使用Math.round()

用這個方法可以實現(xiàn)傳統(tǒng)的四舍五入。

通過 Math.round() 來實現(xiàn)傳統(tǒng)四舍五入


重寫Number.prototype.toFixed()

這個方法則是更加公平的四舍六入五取偶。

重寫 Number.prototype.toFixed()

重寫后的結果:

重寫后在 Chrome 上的結果
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 個人學習批處理的初衷來源于實際工作;在某個迭代版本有個BS(安卓手游模擬器)大需求,從而在測試過程中就重復涉及到...
    Luckykailiu閱讀 4,975評論 0 11
  • 一、JS數(shù)字精度丟失的一些典型問題 1. 兩個簡單的浮點數(shù)相加1 0.1 + 0.2 != 0.3// true ...
    a180754bf396閱讀 6,804評論 0 0
  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法,內部類的語法,繼承相關的語法,異常的語法,線程的語...
    子非魚_t_閱讀 34,633評論 18 399
  • [TOC] 第四周會議 歡迎J的加入 陳杰主要后臺開發(fā) 本周大家的進度 溫江濤: 本周拉進大黑,然后還是看書。周末...
  • 寫在前面 態(tài)度決定高度!讓優(yōu)秀成為一種習慣! 世界上沒有什么事兒是加一次班解決不了的,如果有,就加兩次?。? - ...
    夜盡天明時閱讀 4,676評論 3 9

友情鏈接更多精彩內容