本身整理、設計的,轉載請註明原帖。先從這個demo看起:http://alvarto.github.io/Visu...javascript
關於Number.MAX_VALUE
和Number.MIN_VALUE
:這個結果爲了好看被我四捨五入了……html
關於±0:紫雲飛:JavaScript中的兩個0java
關於數組的最大索引:紫雲飛:JavaScript:數組能越界?git
關於JavaScript能夠精確表示到個位的最大整數:阮一峯:JavaScript數值github
參考國際標準IEEE 754,我畫了一張圖幫助理解:segmentfault
注,這裏的字符是從左到右排的,和wiki之類的資料順序相反。wiki資料考慮的是比較的順序(符號-指數位-有效數字),而我這裏考慮到的是閱讀順序(從0到63位,從左到右)。數組
中間的指數位是如何同時表示正負指數值的呢,和「符號位+有效數字位」的常規表示方法不一樣,指數是使用偏移法來作的:編碼
IEEE 754:指數偏移值spa
指數偏移值(exponent bias),是指浮點數表示法中的指數域的編碼值爲指數的實際值加上某個固定的值,IEEE 754標準規定該固定值爲2^(e-1)-1
,其中的e爲存儲指數的比特的長度。
以單精度浮點數爲例,它的指數域是8個比特,固定偏移值是28-1 - 1 = 128−1 = 127.單精度浮點數的指數部分實際取值是從128到-127。例如指數實際值爲1710,在單精度浮點數中的指數域編碼值爲14410,即14410 = 1710 + 12710.
採用指數的實際值加上固定的偏移值的辦法表示浮點數的指數,好處是能夠用長度爲e個比特的無符號整數來表示全部的指數取值,這使得兩個浮點數的指數大小的比較更爲容易。設計
所以,在JavaScript裏面的指數位,是從1-2^(11-1),也就是從-1023開始,表示了(-1023,1024)這個區間。
實際指數值 | 存儲的指數值 |
-1022 | 1 |
0 | 1023 |
1023 | 2046 |
Number保留了指數值0和2047用於表示一些特殊的值。總的表示表格以下:
X | Y | 表示的值 |
=0 | =0 | ±0 |
≠0 | =2047 | NaN |
=0 | =2047 | ±Infinity |
≠0 | =0 | 反規格化值(Denormalized):f(0.x , 1 , z) |
∈(0,2047) | 規格化值(Normalized):f(1.x , y , z) | |
<h3>f(i,j,k) = (-1)k · 2-1023+j · i</h3> |
前52位能表示的最大值是下面這個(下面是52位+1位默認的1):
parseInt("11111111111111111111111111111111111111111111111111111",2) -> 9007199254740991 //即2^53-1
而下一個值是:
parseInt("100000000000000000000000000000000000000000000000000000",2) -> 9007199254740992 //即2^53
根據內存模型,畫一張圖就能夠知道:
從第2^53位開始,第一個進制被捨棄,這個時候,2^53+1==2^53,每兩個值都會有一個值出現這種不精確的情形。再過N個值,會出現每4個值裏面都有3個值不精確;再過M個值,會出現每2^K個值裏有2^K-1個值不精確;以此類推……(小題目:這個N值是多少?)
驗證:
Number.MAX_VALUE.toString(2) -> "1111111111111111111111111111111111111111111111111111100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" var a = Number.MAX_VALUE.toString(2).split("") , b = [ a.filter(function(i){return i==0}).length , a.filter(function(i){return i==1}).length ] ; b -> [971, 53] Number.MAX_VALUE === (Math.pow(2,53)-1)*Math.pow(2,971) -> true
QED
還記得前面的表格嗎:
X | Y | 表示的值 |
≠0 | =0 | 反規格化值(Denormalized):f(0.x , 1 , z) |
∈(0,2047) | 規格化值(Normalized):f(1.x , y , z) | |
<h3>f(i,j,k) = (-1)k · 2-1023+j · i</h3> |
非規格化值是這樣表示的:
最小正數的內存模型
驗證:
Number.MIN_VALUE.toString(2) -> "0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001" var a = Number.MIN_VALUE.toString(2).split(""); a.filter(function(i){return i==0}).length - 1 -> 1073 Number.MIN_VALUE === Math.pow(2,-1074) -> true
除了IEEE 754的維基頁面,還有這篇文章,解釋的很是清晰:"How numbers are encoded in JavaScript"
最後再推一次:輸入表達式,返回對應Number值的內存模型的DEMO
http://alvarto.github.io/Visu...