javascript避免數(shù)字計算精度誤差的方法詳解
如果我問你 0.1 + 0.2 等于幾?你可能會送我一個白眼,0.1 + 0.2 = 0.3 啊,那還用問嗎?但是你知道嗎,同樣的問題放在編程語言中,或許就不是想象中那么簡單的事兒了。
不信?我們先來看一段 JS。
var numA = 0.1;
var numB = 0.2;
alert( (numA + numB) === 0.3 );
執(zhí)行結(jié)果是 false。沒錯,當我第一次看到這段代碼時,我也理所當然地以為它是 true,但是執(zhí)行結(jié)果讓我大跌眼鏡,是我的打開方式不對嗎?非也非也。我們再執(zhí)行以下代碼試試就知道結(jié)果為什么是 false 了。
var numA = 0.1;
var numB = 0.2;
alert( numA + numB );
原來,0.1 + 0.2 = 0.30000000000000004。是不是很奇葩?其實對于浮點數(shù)的四則運算,幾乎所有的編程語言都會有類似精度誤差的問題,只不過在 C++/C#/Java 這些語言中已經(jīng)封裝好了方法來避免精度的問題,而 JavaScript 是一門弱類型的語言,從設(shè)計思想上就沒有對浮點數(shù)有個嚴格的數(shù)據(jù)類型,所以精度誤差的問題就顯得格外突出。下面就分析下為什么會有這個精度誤差,以及怎樣修復(fù)這個誤差。
首先,我們要站在計算機的角度思考 0.1 + 0.2 這個看似小兒科的問題。我們知道,能被計算機讀懂的是二進制,而不是十進制,所以我們先把 0.1 和 0.2 轉(zhuǎn)換成二進制看看:
0.1 => 0.0001 1001 1001 1001…(無限循環(huán))
0.2 => 0.0011 0011 0011 0011…(無限循環(huán))
雙精度浮點數(shù)的小數(shù)部分最多支持 52 位,所以兩者相加之后得到這么一串 0.0100110011001100110011001100110011001100110011001100 因浮點數(shù)小數(shù)位的限制而截斷的二進制數(shù)字,這時候,我們再把它轉(zhuǎn)換為十進制,就成了 0.30000000000000004。
原來如此,那怎么解決這個問題呢?我想要的結(jié)果就是 0.1 + 0.2 === 0.3 ?。。?!
有種最簡單的解決方案,就是給出明確的精度要求,在返回值的過程中,計算機會自動四舍五入,比如:
var numA = 0.1;
var numB = 0.2;
alert( parseFloat((numA + numB).toFixed(2)) === 0.3 );
但是明顯這不是一勞永逸的方法,如果有一個方法能幫我們解決這些浮點數(shù)的精度問題,那該多好。我們來試試下面這個方法:
Math.formatFloat = function(f, digit) {
var m = Math.pow(10, digit);
return parseInt(f * m, 10) / m;
}
var numA = 0.1;
var numB = 0.2;
alert(Math.formatFloat(numA + numB, 1) === 0.3);
這個方法是什么意思呢?為了避免產(chǎn)生精度差異,我們要把需要計算的數(shù)字乘以 10 的 n 次冪,換算成計算機能夠精確識別的整數(shù),然后再除以 10 的 n 次冪,大部分編程語言都是這樣處理精度差異的,我們就借用過來處理一下 JS 中的浮點數(shù)精度誤差。
如果下次再有人問你 0.1 + 0.2 等于幾,你可要小心回答咯??!
相關(guān)文章
JavaScript callback回調(diào)函數(shù)用法實例分析
這篇文章主要介紹了JavaScript callback回調(diào)函數(shù)用法,結(jié)合實例形式分析了callback回調(diào)函數(shù)的概念、功能、應(yīng)用場景及相關(guān)使用技巧,需要的朋友可以參考下2018-05-05
bootstrap+jQuery實現(xiàn)的動態(tài)進度條功能示例
這篇文章主要介紹了bootstrap+jQuery實現(xiàn)的動態(tài)進度條功能,結(jié)合完整實例形式分析了bootstrap+jQuery實現(xiàn)動態(tài)進度條的具體步驟與相關(guān)操作技巧,需要的朋友可以參考下2017-05-05
js實現(xiàn)Element中input組件的部分功能并封裝成組件(實例代碼)
這篇文章主要介紹了純生js實現(xiàn)Element中input組件的部分功能(慢慢完善)并封裝成組件,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-03-03
驗證用戶是否修改過頁面的數(shù)據(jù)的實現(xiàn)方法
在實現(xiàn)程序的修改模塊時,要在頁面端檢查用戶是否修改過數(shù)據(jù),以便提醒用戶及時保存修改后的數(shù)據(jù)。2008-09-09
react-router-dom?v6?通過outlet實現(xiàn)keepAlive?功能的實現(xiàn)
本文主要介紹了react-router-dom?v6?通過outlet實現(xiàn)keepAlive功能,文中根據(jù)實例編碼詳細介紹的十分詳盡,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-03-03
關(guān)于Mozilla瀏覽器不支持innerText的解決辦法
在各大瀏覽器中,除Mozilla瀏覽器外,幾乎都支持一個元素的屬性:innerText。我們可以通過它來快速獲取某個元素的內(nèi)的文本。2011-01-01

