Javascript作為一門動態(tài)語言节腐,其數(shù)字類型只有Number一種闪唆。 Nubmer類型使用的就是IEEE754標準中的 雙精度浮點數(shù)檀何。Javascript數(shù)字的許多特性都依賴于此標準,例如令人費解的0.1+0.2不等于0.3哲泊。
這篇文章介紹IEEE754標準中雙精度浮點數(shù)二進制儲存格式,并由此推出js中數(shù)字的一些特性催蝗。
一切威、IEEE754中浮點數(shù)的儲存格式
在IEEE754中,雙精度浮點數(shù)儲存為64位:
指數(shù)位可以通過下面的方法轉換為使用的指數(shù)值:
浮點數(shù)表示的值的形式由 和
確定:
二丙号、javascript Number的特性
在js中Number對象上附帶了許多屬性先朦,表示可數(shù)的范圍等信息,例如Number.MAX_SAFE_INTEGER
是一個16位的數(shù)字犬缨,這一部分將解釋如何計算出這些有特殊意義的數(shù)字喳魏。
1.計算Number.MAX_VALUE和Number.MIN_VALUE
當符號位為0、指數(shù)取到1023怀薛、小數(shù)位全為1時刺彩,為可表示的最大值
當符號位為0、指數(shù)位全為0(表示非規(guī)格浮點數(shù))枝恋、小數(shù)位僅最后一位為1時创倔,為可表示的最小正值
var max = (-1)**0 * 2**1023 * (Number.parseInt( "1".repeat(53) ,2) * 2**-52);
max === Number.MAX_VALUE;
// true
var min = (-1)**0 * 2**-1022 * (Number.parseInt( "0".repeat(52)+"1" ,2) * 2**-52);
min === Number.MIN_VALUE;
// true
2.計算Number.MAX_SAFE_INTEGER和Number.MIN_SAFE_INTEGER
Number.MAX_SAFE_INTEGER表示最大安全整數(shù),它是9開頭的16位數(shù)字焚碌,也表明js Number最大精度不超過16位畦攘。
ECMASCRIPT-262定義:
The value of Number.MAX_SAFE_INTEGER is the largest integer n such that n and n + 1 are both exactly representable as a Number value.
http://www.ecma-international...
改變指數(shù)位為53,這讓每個小數(shù)位都表示浮點數(shù)的整數(shù)部分十电,小數(shù)位最低位對應 知押,然后將每個小數(shù)位都置1,可得最大準確整數(shù):
var max_safe_int = (-1)**0 * 2**52 * (Number.parseInt("1".repeat(53),2) * 2**-52);
max_safe_int === Number.MAX_SAFE_INTEGER;
// true
//當它 +1 時鹃骂,可由 (-1)**0 * 2**53 * (Number.parseInt("1"+"0".repeat(52),2) * 2**-52) 正確表示台盯,而再 +1 時則無法準確表示
//符號位取反可得最小安全整數(shù)
-1 * max_safe_int === Number.MIN_SAFE_INTEGER;
3.計算Number.EPSILON
Number.EPSILON是一個極小值,用于檢測計算結果是否在誤差范圍內(nèi)畏线。例如:
Math.abs(0.1 + 0.2 - 0.3) < Number.EPSILON;
// true
//2017-9-27 補充
1.1 + 1.3 - 2.4 < Number.EPSILON
// false
根據(jù)ECMASCRIPT-262定義:
The value of Number.EPSILON is the difference between 1 and the smallest value greater than 1 that is representable as a Number value, which is approximately 2.2204460492503130808472633361816 x 10???16.
http://www.ecma-international...
根據(jù)定義Number.EPSILON是大于1的最小可表示數(shù)與1的差静盅,可以據(jù)此計算出Number.EPSILON的值:
//將表示1的二進制小數(shù)位的最左端置1,可表示大于1的最小數(shù)
var epsilon = (-1)**0 * 2**0 * (Number.parseInt("1"+"0".repeat(51)+"1",2) * 2**-52) - 1;
// (-1)**0 * 2**0 * (+`0b1${"0".repeat(51)}1` * 2**-52) - 1;
epsilon === Number.EPSILON;
// true