1. 程式人生 > 程式設計 >詳細談談JS中的記憶體與變數儲存

詳細談談JS中的記憶體與變數儲存

目錄
  • 前言
  • 神奇的Number
  • 儲存數字
    • 二進位制如何轉換
  • why 0.1 + 0.2 !== 0.3?
    • 總結

      前言

      在前端領域,因為大部分在跟UI打交道,記憶體管理是最容易被忽略的部分。如果不懂記憶體,就看不清很多問題的本質,也難以寫出更合格的程式碼,本次帶大家走進記憶體的世界。

      JS神奇的Number

      案例http://www.cppcns.com一:金額的計算與傳遞

      18.9 * 100
      =1889.9999999999998
      

      案例二:違背的數學定律

      0.1 + 0.2 === 0.3
      // false
      
      (function (a,b,c) {
          return a + b + c === a + ( b + c )
      })(0.1,0.2,0.3)
      // false
      

      案例三:無限迴圈的加法

      (function (num) {
          while(true) {
              if (++num % 13 === 0) {
                  return num
              }
          }
      }www.cppcns.com)(2 ** 53)
      

      案例四:JSON.parse

      JSON.parse('{"a":180143985094813214124}')
      //{a: 180143985094813220000}
      

      通過上面的四個案例我們可以看出,數字在計算機中運算往往會給人帶來一些“驚喜”,要想防止這些意想不到的結果,我們首http://www.cppcns.com

      先要了解Number在中到底是怎麼儲存的?

      儲存數字

      計算機是用二進位制來儲存資料的,所以數字也需要轉換成相應二進位制: 000 或者 111 的不同組合序列。

      二進位制如何轉換

      如何將一個數字轉換成二進位制,這裡舉個例子說明一下:

      把十進位制小數 106.6953125106.6953125106.6953125 轉換成二進位制

      遇到小數轉換時,需要把整數和小數兩部分分別進行處理,整數 106106106 除以 222 直到商是 000 為止,取每次除 222 得到的餘數結果

      106 / 2 = 53  ...... 0
      53  / 2 = 26  ...... 1
      26  / 2 =beBiN 13  ...... 0
      13  / 2 = 6   ...... 1
      6   / 2 = 3   ...... 0
      3   / 2 = 1   ...... 1
      1   / 2 = 0   ...... 1
      結果為得到的餘數按照從右往左排列   1101010
      

      小數 0.69531250.69531250.6953125 乘以 222 直到不存在小數位為止,並計下每次乘後的整數位結果,

      0.6953125 x 2 = 1.390625  ...... 1
      0.390625  x 2 = 0.78125   ...... 0
      0.78125   x 2 = 1.5625    ...... 1
      0.5625    x 2 = 1.125     ...... 1
      0.125     x 2 = 0.25      ...... 0
      0.25      x 2 = 0.5       ...... 0
      0.5       x 2 = 1         ...... 1
      結果為得到的整數位按照從左往右排列   1011001
      

      將計算後的 000 111 序列拼在一起就得到轉換的二進位制 1101010.10110011101010.10110011101010.1011001,用科學計數法表示為1.1010101011001∗261.1010101011001*2^61.1010101011001∗26,算出了二進位制,接下來需要將它存進計算機中,在script中不區分整數和小數,數字統一按照雙精度浮點數的要求來儲存,主要包含下面規則:

      • 使用 8bytes(64bits)8bytes(64bits)8bytes(64bits) 儲存雙精度浮點數
      • 儲存小數用科學計數法表示的資料
      • 第一位表示符號,後 111111 位表示指數,指數按照補位運算,即直接 102310231023 加指數位
      • 剩餘 525252 位表示小數點後的尾數,超過 525252 位的部分 000 舍 111 進

      由於指數位的 11 位不包括符號位,那麼為了達到正負指數的效果,就引入了指數的偏移值。

      用圖表示如下:

      詳細談談JS中的記憶體與變數儲存

      我們將轉換好的二進位制數按規則放進記憶體中,首先 106.6953125106.6953125106.6953125 是正數,所以符號位應該為 111, 000 表示正號, 111 表示負號(圖片應該為顯示 000,筆誤了)

      詳細談談JS中的記憶體與變數儲存

      二進位制 1.1010101011001∗261.1010101011001*2^61.1010101011001∗26 指數是 666(這裡需要加上偏移量1023),轉成二進位制為 100000001011000000010110000000101,指數位要求放置二進位制的補碼,而補碼的計算規則是:

      • 正數的補碼就是其本身
      • 負數的補碼是在其原碼的基礎上,符號位不變,其餘各位取反,最後+1. (即在反碼的基礎上+1)
      [+1] = [00000001]原 = [00000001]反
      
      [-1] = [10000001]原 = [11111110]反
      

      所以圖片指數位應該填

      詳細談談JS中的記憶體與變數儲存

      尾數位部分直接將小數轉換後的二進位制填入即可

      詳細談談JS中的記憶體與變數儲存

      數字最後就是以這樣的形式存入計算機中

      why 0.1 + 0.2 !== 0.3?

      在理解數字儲存的原理後,我們再來分析下為什麼 0.1+0.2!==0.30.1 + 0.2 !== 0.30.1+0.2!==0.3

      首先將 0.10.10.1 0.20.20.2 0.30.30.3 分別轉換成二進位制

      0.1 x 2 = 0.2  ...... 0
      0.2 x 2 = 0.4  ...... 0
      0.4 x 2 = 0.8  ...... 0
      0.8 x 2 = 1.6  ...... 1
      0.6 x 2 = 1.2  ...... 1
      0.2 x 2 = 0.4  ...... 0
      0.4 x 2 = 0.8  ...... 0
      0.8 x 2 = 1.6  ...... 1
      0.6 x 2 = 1.2  ...... 1
      得到的整數位按照從左往右排列   000110011...
      

      0.1→0.00011(0011)∞

      0.2 x 2 = 0.4  ...... 0
      0.4 x 2 = 0.8  ...... 0
      0.8 x 2 = 1.6  ...... 1
      0.6 x 2 = 1.2  ...... 1
      0.2 x 2 = 0.4  ...... 0
      0.4 x 2 = 0.8  ...... 0
      0.8 x 2 = 1.6  ...... 1
      0.6 x 2 = 1.2  ...... 1
      0.2 x 2 = 0.4  ...... 0
      得到的整數位按照從左往右排列   001100110...
      

      0.2→0.00110(0110)∞

      0.3 x 2 = 0.6  ...... 0
      0.6 x 2 = 1.2  ...... 1
      0.2 x 2 = 0.4  ...... 0
      0.4 x 2 = 0.8  ...... 0
      0.8 x 2 = 1.6  ...... 1
      0.6 x 2 = 1.2  ...... 1
      0.2 x 2 = 0.4  ...... 0
      0.4 x 2 = 0.8  ...... 0
      0.8 x 2 = 1.6  ...... 1
      得到的整數位按照從左往右排列   010011001...
      

      0.3→0.01001(1001)∞

      統一用科學計數法表示為

      0.1→0.00011(001beBiN1)∞→1.(1001)∞∗2−4

      0.2→0.00110(0110)∞→1.(1001)∞∗2−3

      0.3→0.01001(1001)∞→1.(0011)∞∗2−2

      放入計算機中雙精度浮點數儲存,最後的紅色表示超過尾數位的二進位制,即需要做舍0進1處理

      詳細談談JS中的記憶體與變數儲存

      則經過64位雙精度儲存後,二進位制如下表示
      0.1→0−01111111011−(1001)121010

      0.2→0−01111111100−(1001)121010

      0.3→0−01111111101−(0011)120011

      此時 0.1+0.20.1 + 0.20.1+0.2 可以看出與 0.30.30.3 不相等

      詳細談談JS中的記憶體與變數儲存

      這就是數字在計算機中運算往往會給人帶來一些“驚喜”!

      總結

      到此這篇關於JS中記憶體與變數儲存的文章就介紹到這了,更多相關JS記憶體與變數儲存內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!