浮點數相加

浮點數

在日常生活中,如果要計算 0.1 + 0.2,我們能夠直覺的答出 0.3 這個答案。
但是在 JavaScript 中,計算結果卻不如預期,用 console.log(0.1 + 0.2 === 0.3) 回傳的結果竟會得到 false
其實這和電腦的「IEEE754 二進制浮點運算」計算方式有關,當我們宣告一段浮點數陣列,展開後會發現,有些浮點數會有些微誤差,以致於在進行計算時會出錯。
所以得到的結果自然是 0.1 + 0.2 !== 0.3

1
2
3
4
5
var num = Array.from(Array(10).keys())
var result = num.map(item => item * 0.1)
console.log(result)
// 0, 0.1, 0.2, 0.30000000000000004, 0.4, 0.5,
// 0.6000000000000001, 0.7000000000000001, 0.8, 0.9

該如何解決浮點數問題呢?可以使用以下兩種方法:

  • Number.toFixed()
  • Number.toPrecision()

Number.toFixed

Number.toFixed() 可以對數字進行四捨五入到指定的第 N 位數。

toFixed() 方法回傳的型別是「字串」,需要另外再轉換為數字型別。

1
2
3
var num = 10.12345
num.toFixed(2) // "10.12"
num.toFixed(4) // "10.1235"

同樣方法用在浮點數上可以改成:

1
2
3
4
var num = Array.from(Array(10).keys())
var result = num.map(item => Number((item * 0.1).toFixed(1)))
console.log(result)
// [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9]

如果想去除小數點後為 0 的尾數,則可以用 parseFloat()

1
2
var num = 0.990
parseFloat(num) // 0.99

Number.toPrecision

Number.toPrecision() 方法可以指定想要顯示的浮點數範圍,範圍在 1~21,並且回傳「字串」。
toPrecision() 方法有以下幾種狀況:

1
2
3
4
5
6
7
8
9
10
11
// 1. 數字是浮點數,就會補 0
var num1 = 0.12
num1.toPrecision(5) // "0.12000"

// 2. 數字是浮點數,但位數不足,一樣會四捨五入
var num2 = 12.345
num2.toPrecision(4) // "12.35"

// 3. 數字是整數,但是位數不足,會轉換成指數寫法
var num3 = 1234
num3.toPrecision(3) // "1.23e+3"

所以如果想要解決浮點數相加的問題,可以改成這樣:

1
2
parseFloat((0.1 + 0.2).toPrecision(12)) // "0.3"
parseFloat((0.6 + 0.7).toPrecision(12)) // "1.3"

至於為什麼參數要帶 12,因為 12 位數可以避免大部分浮點數的問題。


參考文章