很經典的例子是0.1+0.2!=0.3(實際等於 0.30000000000000004)
不等的原因
機器中采用二進制存儲數據,
比如,35會被存儲為: 00100011 (2^5 + 2^1 + 2^0)。
0.375會被存儲為: 0.011 (1/2^2 + 1/2^3 = 1/4 + 1/8 = 0.375)
而對於像0.1轉換為二進制表示,就會發現無法整除,算下來會是 0.00011001100110011...(0011無限循環)
0.2轉換為二進制為:0.001100110011...(0011無限循環)
由於存儲空間有限,計算機會舍棄后面的數值,所以機器中存儲的就是一個近似值。
而以近似值為基礎進行運算,則會出現結果0.30000000000000004的情況
對於JS來說,其不夠近似於0.3,於是就出現了0.1 + 0.2 != 0.3 這個現象。 當然,也並非所有的近似值相加都得不到正確的結果。有時兩個近似值進行計算的時候,得到的值是在JS的近似范圍內的,於是就可以得到正確答案。
Reat項目引用Math.js處理浮點數精度問題
我們借助 Math.js 這個庫來處理浮點數的精度問題
下載
npm install mathjs
在react中引入並配置
import { create, all } from 'mathjs'
const config = {
epsilon: 1e-12,
matrix: 'Matrix',
number: 'BigNumber', // 可選值:number BigNumber
precision: 64,
predictable: false,
randomSeed: null
}
const math = create(all, config)
-
用靜態函數和常數(就像JavaScript的Math對象)
math.round(math.e, 3); // 2.718 math.add(2, 3); // 5 math.sqrt(-4); // 2i math.pow([[-1, 2], [3, 1]],2); // [[7, 0], [0, 7]] math.derivative('x^2 + x', 'x'); // 2 * x + 1 math.atan2(3, -3) / math.pi; // 0.75
-
對字符串表達式進行求值運算
math.evaluate('12 / (2.3 + 0.7)'); // 4 math.evaluate('12.7 cm to inch'); // 5 inch math.evaluate('sin(45 deg) ^ 2'); // 0.5 math.evaluate('9 / 3 + 2i'); // 3 + 2i math.evaluate('det([-1, 2; 3, 1])'); // -7
在對字符串表達式進行求值計算的時候,計算的結果是 mathjs 定義的類型,我們可以將其轉換成 字符串 以得到正常的結果
-
鏈式操作
math.chain(3) .add(4) .multiply(2) .done(); // 14
-
矩陣操作
var n = math.matrix([[4,3,2], [6,6,8], [7,4,5]]); console.log(n.valueof()); // [[4,3,2],[6,6,8],[7,4,5]]
注:大多數math.js函數,都需要
valueof()
或者done()
函數來真正地獲取操作的值,如上面代碼所示。
注意
-
如果 config 配置項中的 number 屬性值設為
number
,那么仍然會有精度問題math.add(0.1, 0.2) // 0.30000000000000004 加:math.format(math.add(math.bignumber(1.1),math.bignumber(2.2))) // 3.3 減:math.format(math.subtract(math.bignumber(1.1),math.bignumber(2.2))) 乘:math.format(math.multiply(math.bignumber(1.1),math.bignumber(2.2))) 除:math.format(math.divide(math.bignumber(1.1),math.bignumber(2.2)))
bignumber() 方法是進行數值類型聲明,即表示該數值類型是浮點數,需要進行精度計算
-
當為 config 配置項中的 number 屬性值設置
BigsNumber
之后,能夠解決精度問題。math.format(math.evaluate('1.1+2.2')) // 3.3 --> string 類型
format()方法是格式化校驗方法,把math方法計算出的值以字符串的形式顯示最終的結果
參考文章:
https://www.jianshu.com/p/96c90f03679d
https://www.jianshu.com/p/4f63f0003a56