問你一個問題:JS
中 Number
類型數據總共有多少個?html
這有答案嗎?git
《Ecma-262 Edition 5.1》給出的答案是:18437736874454810627,即 。github
那麼,具體是怎麼算出來的??app
本文主要解決這個問題。less
規範上說,Number
類型使用的是《 IEEE二進制浮點數算術標準(IEEE 754)》的雙精度 64 位格式。koa
其核心問題:是怎麼用 64 個比特位,來表示一個具體浮點類型數值?jsp
《IEEE 754.pdf》把這 64 位比特分紅 3 部分: ui
其中,s
表示符號位,佔 1 比特;e
表示指數位,佔 11 比特;f
表示分數位,佔 52 比特。spa
規範裏詳細地給出了各類狀況所對應的值:3d
上述分類是符合 MECE 原則的,不重複且不遺漏。
其中 e
佔 11 位,所以該部分能表示的數字範圍是 0 至 2047,即,0 至。分類首先標準就是看
e
是否位於邊界。
前兩條是指當 e
部分都填充二進制 1 時,即當指數部分爲最大值時,表示 NaN
和正負 Infinity
這兩種狀況。
具體來講,第一種,當小數部分同時不爲零時,此時表示 NaN
。JS
中的字面量 NaN
,正是對應這種狀況,另外要求 NaN
始終不能等於自身。
第二種,而當 f
部分爲 0 時,根據符號位的正負,來表示相應的正負無窮。
第三條是指當 e
在介於最小值和最大值之間的情形。此時被稱爲規範化數字,有別於下面的第四條。這裏值的肯定方式是 。此時要注意
指的是二進制小數。
舉個例子,假設某個數字的 64 位比特表示以下: 1|10000000001|110000...
,此時 s
是 1, e
是 ,即 1025。那麼該數據對應的值
v
是: 而二進制小數
其值是
,即
1.75
。所以該表示是 -7。
第四條是指非規範化數字情形。此時數字已經很是小了。注意這裏是二進制小數是 不一樣於第三條裏的
。最後一類是正負 0 的情形。
咱們已經把規範過了一遍,如今,咱們來算算開頭的問題:Number
類型共有多少個值?
從上述分類中能夠看出:後三類是正常值,前兩類總共有 種可能(排列組合原理,
s
部分爲 2047,所以相應的只有一種可能),這麼多種可能,卻在 JS
中只表示 NaN
、+Infinity
、-Infinity
這 3 個值。所以總數 。
至此,本文接近尾聲了。
最後提醒一下,閱讀《Ecma-262 Edition 5.1》8.5節不要犯迷糊:
The 18437736874454810622 (that is,
) finite nonzero values are of two kinds: 18428729675200069632 (that is,
)of them are normalised, having the form
![]()
where s is +1 or −1, m is a positive integer less thanbut not less than
, and e is an integer ranging from −1074 to 971, inclusive.
The remaining 9007199254740990 (that is,) values are denormalised, having the form
![]()
where s is +1 or −1, m is a positive integer less than, and e is −1074.
其中提到了 e
是從 -1070 到 971,這兩個數字怎麼來的?其實它與《IEEE 754.pdf》說的是同一回事,好比規範化情形,只是從指數部分裏拿出了 放到了
m
裏面。 m
等價於。
本文完。