一文解決前端JS小數(shù)運算精度問題
前言
在做項目的時候,前端需要在表格的底部做一個匯總的功能,在采用reduce對當前屬性所有值匯總時,發(fā)現(xiàn)匯總結果存在好長的小數(shù)位,本以為后端的數(shù)據(jù)就存在精度這么小的數(shù)據(jù),后來,檢查發(fā)現(xiàn)后端精度只有三位小數(shù),但前端計算結果為什么會這樣呢?
JS存在精度問題
在控制臺可以試一下 0.1 + 0.2 的結果是0.30000000000000004 js的運算下 0.1 + 0.2 != 0.3
由于計算機在存儲和計算數(shù)字的時候,使用的是二進制形式,有些十進制數(shù)據(jù)再轉(zhuǎn)換成二進制時,無法精確表示。
JS在數(shù)字運算的時候,當存在浮點數(shù)的運算時,就有可能會出現(xiàn)精度誤差,有些小數(shù)無法用二進制精確表示。
JavaScript采用的是雙精度(64位)浮點運算規(guī)則,遵循的是IEEE二進制浮點數(shù)算法標準。其中有1位用作符號位,11位為階碼,尾數(shù)有52位。有興趣詳細了解的可以查閱相關資料。
比如 十進制0.1 -> 二進制表示為0.0001 1001 1001 1001...(1100循環(huán)) 十進制0.2 -> 二進制表示為0.0011 0011 0011 0011...(0011循環(huán)) EEE 754 標準的 64 位雙精度浮點數(shù)的小數(shù)部分最多支持53位二進制位,所以兩者相加之后得到二進制為: 0.1 + 0.2 = 0.0100110011001100110011001100110011001100110011001100 因浮點數(shù)小數(shù)位的限制而截斷的二進制數(shù)字,再轉(zhuǎn)換為十進制,就成了0.30000000000000004。
解決方案
思路:
- 將小數(shù)轉(zhuǎn)化成整數(shù)進行計算,規(guī)避浮點數(shù)運算問題。
- 整數(shù)的加減乘運算結果不會出現(xiàn)浮點數(shù),不會存在精度問題,但除法會出現(xiàn)浮點數(shù),因此用toFixed()方法截掉無效的小數(shù)位。
- 將string轉(zhuǎn)回number輸出
/** 封裝一個公共方法numberCalculate() 用于浮點數(shù)運算 */ //num1 num2傳入兩個值 symbol +-*/符號 numberCalculate(num1: number, num2: number, symbol: string) { var str1 = num1.toString(), str2 = num2.toString(), result, str1Length, str2Length try { //獲取小數(shù)點后的精度 str1Length = str1.split('.')[1].length } catch (error) { //解決整數(shù)沒有小數(shù)點方法 str1Length = 0 } try { str2Length = str2.split('.')[1].length } catch (error) { str2Length = 0 } // 取兩個數(shù)的最小精度,即小數(shù)點后數(shù)字的最大長度 var maxLen = Math.max(str1Length, str2Length) // step將兩個數(shù)都轉(zhuǎn)化為整數(shù)至少小數(shù)點后移多少位 var step = Math.pow(10, maxLen) switch (symbol) { case "+": // toFixed()根據(jù)最小精度截取運算結果 result = ((num1 * step + num2 * step) / step).toFixed(maxLen) break; case "-": result = ((num1 * step - num2 * step) / step).toFixed(maxLen) break; case "*": result = (((num1 * step) * (num2 * step)) / step / step).toFixed(maxLen) break; case "/": result = ((num1 * step) / (num2 * step)).toFixed(maxLen) break; default: break; } // 由于toFixed方法返回結果是字符串,還需要轉(zhuǎn)回number輸出 return Number(result) }
0.1 + 0.2的計算,就可以調(diào)用numberCalculate(0.1,0.2,'+')進行計算了。
以上就是一文解決前端JS小數(shù)運算精度問題的詳細內(nèi)容,更多關于JS小數(shù)運算精度的資料請關注腳本之家其它相關文章!
相關文章
解決uni-app報錯Error:?read?EBADF?at?Pipe?.?onStreamRead...
這篇文章主要介紹了uni-app報錯Error:?read?EBADF?at?Pipe?.?onStreamRead...解決方法,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-08-08工作中比較實用的JavaScript驗證和數(shù)據(jù)處理的干貨(經(jīng)典)
工作中比較實用的JavaScript驗證和數(shù)據(jù)處理知識經(jīng)常會用到,下面小編通過查閱相關資料及日常記錄的知識分享到腳本之家平臺,供大家參考2016-08-08