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複製代碼
到此問題獲得瞭解決,而且基本能覆蓋到全部正常狀況。
最後要說的是,關於數值計算精度問題在開發中必定要當心,稍有不慎就會掉入超長浮點數的坑裏,在此也是記錄而且告訴下本身,避免後面再次入坑。