JavaScript 使用 IEEE 754 標準的雙精度浮點數來表示數字,這會導致在進行某些計算時出現精度問題,例如 0.1 + 0.7 的結果不是 0.8,而是 0.7999999999999999。這是因為 0.1 和 0.7 不能用二進位制精確表示,就像 1/3 不能用十進位制精確表示一樣。
以下是一些避免 JavaScript 浮點運算精度問題的常用方法:
1. 使用整數進行計算:
如果可能的話,將浮點數轉換為整數進行計算,然後再轉換回浮點數。例如,計算金額時,可以用分而不是元作為單位進行計算。
// 錯誤示範
let total = 0.1 + 0.2; // 0.30000000000000004
// 正確示範
let price1 = 10; // 分
let price2 = 20; // 分
let totalInCents = price1 + price2; // 30 分
let total = totalInCents / 100; // 0.3
2. 使用toFixed()方法進行舍入:
toFixed()
方法可以將數字轉換為字串,並保留指定的小數位數。這對於顯示結果很有用,但要注意它返回的是字串,而不是數字。
let total = 0.1 + 0.2;
let roundedTotal = total.toFixed(2); // "0.30"
// 如果需要數字型別,則需要再轉換
let roundedTotalNumber = parseFloat(roundedTotal); // 0.3
3. 使用庫:
一些庫,例如 decimal.js、bignumber.js 和 Math.js,提供了任意精度的小數運算。這些庫可以避免浮點精度問題,但會增加程式碼的複雜性和大小。 推薦使用 decimal.js,因為它體積相對較小,且效能良好。
// 使用 decimal.js
const Decimal = require('decimal.js');
let x = new Decimal(0.1);
let y = new Decimal(0.2);
let result = x.plus(y); // result = 0.3
console.log(result.toString()); // "0.3"
4. 比較浮點數時使用 Number.EPSILON:
Number.EPSILON
表示 JavaScript 中可以表示的最小浮點數。在比較兩個浮點數是否相等時,可以使用它來判斷它們之間的差值是否小於 Number.EPSILON
。
function areEqual(a, b) {
return Math.abs(a - b) < Number.EPSILON;
}
let x = 0.1 + 0.2;
let y = 0.3;
console.log(areEqual(x, y)); // true
5. 理解精度限制,並選擇合適的策略:
並非所有場景都需要絕對的精度。例如,在展示商品價格時,通常保留兩位小數就足夠了。在進行科學計算或金融計算等需要高精度的情況下,則需要使用專門的庫。
選擇哪種方法取決於具體的應用場景。對於簡單的計算,toFixed()
方法可能就足夠了。對於需要高精度的計算,則需要使用專門的庫。 理解浮點數的侷限性,並選擇合適的策略,是避免精度問題的關鍵。