js小數計算的問題,為什麼0.1+0.2 != 0.3

dykily發表於2019-02-26

簡介

因為 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浮點數相加相減的問題的大家可以去看一下

github.com/dykily/easy…

大家覺得有用的話給個star呀

相關文章