js數值計算精度再次入坑

js數值類型計算一直有一個坑,就是關於計算精度的問題。在js中計算 0.1+0.二、0.3-0.1等運算時,會出現很驚人的一大串數值,相信不少人都遇到過前端

0.1+0.2  //0.30000000000000004
0.3-0.1  //0.19999999999999998複製代碼

關於產生這個問題的緣由,網上已經有不少說明了,大致就是js浮點類型精度的問題致使的,所以在計算的時候咱們一般會採起一些方法,截取所須要的值。後端

回到正題,此次遇到的坑也是精度問題,可是不是加減法而是乘法,一個浮點數乘以10,結果也是驚人的長————————bash

0.68*10  //6.800000000000001複製代碼

可能不少人遇到過乘法精度問題,可是我確實是第一次遇到這種問題。問題產生的背景是,後端返回一個浮點數m,前端在此基礎上乘10,轉換爲「m折」字樣展示在頁面上。需求很簡單,可是卻有一個隱藏的坑。app

其實要解決這個坑並不難,網上也有不少辦法,此處列舉幾個:ui

1)toFixed方法spa

浮點數*10而後調用toFixed方法能夠解決此問題,可是也有一個問題,就是會存在四捨五入的問題,若是要求準確的展現後臺返回的數值,這個方法就會有缺陷。code

(0.68*10).toFixed(2)  //此時沒問題,結果爲6.80
(0.0686*10).toFixed(2)  //小數位數多的時候就會有四捨五入問題,此時結果爲0.69複製代碼

(2)將浮點數乘以10的倍數,再除以相應的10的倍數開發

這個方法也很經常使用,就是將浮點數轉化爲整數,在除以相應的倍數轉換爲浮點數。這個方法基本能夠覆蓋很大部分問題,可是一種方法不試用,就是浮點數的位數不肯定的時候,沒法準確判斷乘以10的準確倍數。字符串

0.68*1000/100   //此時結果正常,結果爲6.8

假如返回的浮點數不肯定位數,可是依舊按乘1000/100方式計算
0.00000068*1000/100   //結果又很給力了, 結果爲0.000006799999999999999複製代碼

(3)利用Math相關方法轉換string

此方法主要是利用Math.round和Math.pow方法對數據進行處理,借用網上的一個方法

function myFixed(a, b) {
  return Math.round(a * Math.pow(10, b)) / Math.pow(10, b);
}
console.log(0.68*10);              //6.800000000000001
console.log(myFixed(0.68*10, 2));  //6.8複製代碼

4)字符串轉換方法

最後說一下咱們填坑的方法,由於此處對數值的應用只是將其轉化爲折扣數值,能夠說是不須要進行運算處理的,所以採用了一個直截了當的字符串截取的方法,直接上代碼:

//此方法考慮數值都是大於等於0的數值,而且對0和大於1的數值進行了展現(理論上折扣券不會出現0和大於1的狀況)
function discounts(discountNumber){  
    if (!discountNumber && discountNumber !== 0) {
        return  
    }  
    const expPoint = /\./
    let countString = String(discountNumber)  
    let discountString = ''  
    if(countString < 1 && expPoint.test(countString)){    
        let discountArr = countString.split('.')[1].split('')    
        if(discountArr.length === 1){      
            discountString = discountArr[0]    
        }else{      
            let discountStringFirst = discountArr[0]      
            let discountStringSecond = discountArr.slice(1).join('')      
            discountString = discountStringFirst + '.' + discountStringSecond
        }
    }else{    
        discountString = countString * 10  
    }  
    return discountString
}

discounts(0)     //0
discounts(0.3)   //3
discounts(0.68)  //6.8
discounts(0.9)   //9
discounts(1)     //10
discounts(1.02)  //10.2複製代碼

到此問題獲得瞭解決,而且基本能覆蓋到全部正常狀況。

最後要說的是,關於數值計算精度問題在開發中必定要當心,稍有不慎就會掉入超長浮點數的坑裏,在此也是記錄而且告訴下本身,避免後面再次入坑。

相關文章
相關標籤/搜索