簡介
因為 JS 採用 IEEE 754 雙精度版本(64位),並且只要採用 IEEE 754 的語言都有該問題。 還有學過計算機組成原理這門課的同學應該知道,我們計算機的資料都是由0、1組成的,js的數字最終在計算機也是又0、1組成。我們先說一下小數怎麼轉換成二進位制。
// 0.125 十進位制 -> 二進位制
0.125 * 2 = 0.25 取0
0.25 * 2 = 0.5 取0
0.5 * 2 = 1 取1
// 0.001 (0.125 的二進位制)
複製程式碼
從上面我們可以知道通過小數部分不斷乘2來判斷取二進位制位 0 還是 取1,以下是轉換的步驟:
- 1、把當前小數乘2,小於1走 步驟2,大於1 走 步驟3,等於1走 步驟4,
- 2、如果小數部分乘2不超過1,二進位制位則取0,回到 步驟1
- 3、如果乘2後超過1則取1並不用考慮小數點左邊的數字保留小數點右邊的數字,二進位制位取1 回到 步驟1
- 4、如果小數乘2剛好等於1則結束轉換,二進位制位取1
如果上面還不清楚可以再下面
// 0.1 十進位制 -> 二進位制
0.1 * 2 = 0.2 取0
0.2 * 2 = 0.4 取0
0.4 * 2 = 0.8 取0
0.8 * 2 = 1.6 取1
0.6 * 2 = 1.2 取1
0.2 * 2 = 0.4 取0
0.4 * 2 = 0.8 取0
0.8 * 2 = 1.6 取1
0.6 * 2 = 1.2 取1
//0.000110011(0011)` 0.1二進位制(0011)裡面的數字表示迴圈
複製程式碼
你會發現 0.1 轉二級制會一直無線迴圈下去,根本算不出一個正確的二進位制數。
所以我們得出 0.1 = 0.000110011(0011)
,那麼 0.2 的演算也基本如上所示,所以得出 0.2 = 0.00110011(0011)
回來繼續說 IEEE 754 雙精度。六十四位中符號位佔一位,整數位佔十一位,其餘五十二位都為小數位。
因為 0.1 和 0.2 都是無限迴圈的二進位制了,所以在小數位末尾處需要判斷是否進位(就和十進位制的四捨五入一樣)
那麼把這兩個二進位制加起來會得出0.010011....0100
, 這個值算成十進位制就是 0.30000000000000004
小結
//下面可以用原生解決 0.1+0.2 的問題
parseFloat((0.1 + 0.2).toFixed(10))
複製程式碼
下面推薦一個小工具專門是用來處理js浮點數相加相減的問題的大家可以去看一下
大家覺得有用的話給個star呀