上篇博客深度剖析了0.1+0.2 === 0.30000000000000004的緣由。
這篇博客將主要提供幾種解決小數精度丟失問題的Javascript類庫的代碼示例,以及簡單的原生EcmaScript方法的代碼示例。css
math.js是JavaScript和Node.js的一個普遍的數學庫。支持數字,大數,複數,分數,單位和矩陣等數據類型的運算。git
官網:http://mathjs.org/
GitHub:https://github.com/josdejong/mathjsgithub
0.1+0.2 ===0.3實現代碼:npm
var math = require('mathjs') console.log(math.add(0.1,0.2))//0.30000000000000004 console.log(math.format((math.add(math.bignumber(0.1),math.bignumber(0.2)))))//'0.3'
爲 JavaScript 提供十進制類型的任意精度數值。api
官網:http://mikemcl.github.io/decimal.js/瀏覽器
GitHub:https://github.com/MikeMcl/decimal.js測試
var Decimal = require('decimal.js') x = new Decimal(0.1) y = 0.2 console.log(x.plus(y).toString())//'0.3'
用於任意精度算術的JavaScript庫。網站
官網:http://mikemcl.github.io/bignumber.js/ui
Github:https://github.com/MikeMcl/bignumber.jsspa
var BigNumber = require("bignumber.js") x = new BigNumber(0.1) y = 0.2 console.log(x.plus(y).toString())//'0.3'
用於任意精度十進制算術的小型快速JavaScript庫。
官網:http://mikemcl.github.io/big.js/
Github:https://github.com/MikeMcl/big.js/
var Big = require("big.js") x = new Big(0.1) y = 0.2 console.log(x.plus(y).toString())//'0.3'
有一個須要注意的點,使用類庫此時輸出的0.3是String類型,所以若想保持爲Number類型,可以使用parseFloat()方法。
還有一個注意點,在本地install測試的時候,npm i mathjs -g ,require是也要require('mathjs'),而不是帶點的math.js,由於josdejong這哥們在建立項目的時候就命名爲mathjs,而同時擁有上述decimal.js, bignumber.js和big.js的MikeMcl,項目名字就帶了dot,所以安裝和引入時,都是xxx.js的形式。
如何在這三個類庫之間作選擇,還須要你們本身根據具體狀況具體分析,我在這裏就不贅述了。
最後,教你們一個線上直接測試的網站,https://npm.runkit.com,子路徑輸入想要測試的Node.js package名,就能夠實如今線測試包中的api了。
例如:
math.js:https://npm.runkit.com/mathjs
big.js:https://npm.runkit.com/big.js
類庫其實很強大,咱們計算0.1+0.2其實只是用到了冰山一角,那麼咱們如何使用原生的EcmaScript代碼來應用於簡單的問題場景呢?
這就要用到Number.prototype.toFixed()這個方法了。
浮點數運算
toFixed() 方法
浮點數運算的解決方案有不少,這裏給出一種目前經常使用的解決方案, 在判斷浮點數運算結果前對計算結果進行精度縮小,由於在精度縮小的過程總會自動四捨五入。
toFixed() 方法使用定點表示法來格式化一個數,會對結果進行四捨五入。語法爲:
JavaScript 代碼:
numObj.toFixed(digits)
參數 digits 表示小數點後數字的個數;介於 0 到 20 (包括)之間,實現環境可能支持更大範圍。若是忽略該參數,則默認爲 0。
返回一個數值的字符串表現形式,不使用指數記數法,而是在小數點後有 digits 位數字。該數值在必要時進行四捨五入,另外在必要時會用 0 來填充小數部分,以便小數部分有指定的位數。 若是數值大於 1e+21,該方法會簡單調用 Number.prototype.toString()並返回一個指數記數法格式的字符串。
特別注意:toFixed() 返回一個數值的字符串表現形式。
具體能夠查看 MDN中的說明,那麼咱們能夠這樣解決精度問題:
JavaScript 代碼:
parseFloat((數學表達式).toFixed(digits)); // toFixed() 精度參數須在 0 與20 之間 // 運行 parseFloat((0.1 + 0.2).toFixed(10))//結果爲0.3 parseFloat((0.3 / 0.1).toFixed(10)) // 結果爲 3 parseFloat((0.7 * 180).toFixed(10))//結果爲126 parseFloat((1.0 - 0.9).toFixed(10)) // 結果爲 0.1 parseFloat((9.7 * 100).toFixed(10)) // 結果爲 970 parseFloat((2.22 + 0.1).toFixed(10)) // 結果爲 2.32
在Browser環境精度參數容許0~100位之間(包括100),測試版本爲Chrome62(64位)和Firefox56 (32 位)。
在Nodejs環境中,只能是0~20之間,測試版本爲v6.9.5。
其次就是toFixed()的瀏覽器兼容性討論,MDN給出的結果所有是YES,不管desktop端仍是mobile端,也就是說不用擔憂toFixed()的兼容性問題(ie8- 咱們不作討論)。
desktop端:
mobile端:
Thanks:
http://www.css88.com/archives...
https://developer.mozilla.org...