javascript只有一種數字類型,它在內部被表示爲64位的浮點數,和java的double數字類型同樣。與其餘大多數編程語言不一樣的是,它沒有分離出整數類型,因此1和1.0的值相同。這提供了很大的方便,避免了一大堆因數字類型致使的錯誤javascript
數字Number是javascript中基本的原始數據類型,同時javascript也支持Number對象,它是一個原始數值的包裝對象。在須要時,javascript會自動在原始形式和對象形式之間轉換。本文將介紹數字Number原始類型及Number包裝對象html
javascript採用IEEE754格式來表示數字,不區分整數和浮點數,javascript中的全部數字都用浮點數值表示java
因爲浮點型數值須要的內存空間是保存整數值的兩倍,所以javascript會不失時機地將浮點數值轉換成整數值,若小數點後沒有跟任何數字或者浮點值自己表示的就是一個整數,這個數值會做爲整數值來保存編程
console.log(1.0,1.0===1);//1 true console.log(1.,1.===1);//1 true
當一個數字直接出如今javascript程序中時,稱之爲數字字面量(numeric literal)。而當Number()使用new操做符用作構造函數時,稱之爲Number對象數組
javascript的整數表示共有四種字面量格式是十進制、二進制、八進制、十六進制。但在進行算術計算時,全部以二進制、八進制和十六進制表示的數值最終都將被轉換成十進制數值編程語言
【1】八進制字面值的第一位必須是0,而後是八進制數字序列(0-7)。若是字面值中的數值超出了範圍,那麼前導0將被忽略,後面的數值被看成十進制數解析函數
[注意]因爲某些javascript的實現不支持八進制字面量,且八進制字面量在嚴格模式下是無效的,會致使javascript拋出錯誤。因此儘可能不使用八進制字面量ui
【2】十六進制字面值的前兩位必須是0x,後跟十六進制數字序列(0-9,a-f),字母可大寫可小寫。若是十六進制中字面值中的數值超出範圍,如出現g、h等會報錯spa
【3】二進制字面值的前兩位必須是0b,若是出現除0、1之外的數字會報錯設計
var num2 = 0b101; console.log(num2);//5 var num2 = 0b2; console.log(num2);//報錯 var num8 = 012; console.log(num8);//10 var num8 = 09; console.log(num8);//9 var num16 = 0x11; console.log(num16);//17 var num16 = 0xg; console.log(num16);//報錯
浮點數(floating-point number)是指數值中必須包含一個小數點,且小數點後面必須至少有一位數字。與整數支持多進制不一樣,通常地,浮點數只可用十進制表示
var num1 = 011.1;//報錯 var num2 = 0x11.1;//報錯 var num3 = 011e1;//報錯 var num4 = 0x11e1;//出錯,會被識別成整數,結果爲4577
[注意]雖然小數點前面能夠沒有整數,但不推薦
var num1 = 1.1; var num2 = 1.; var num3 = .1; console.log(num1,num2,num3);//1.1,1,0.1
因爲javascript採用IEEE754格式表示數字,浮點數不是精確值,因此涉及浮點數的比較和運算時要特別當心
console.log(0.1 + 0.2 === 0.3);// false console.log(0.3 / 0.1);// 2.9999999999999996 console.log((0.3 - 0.2) === (0.2 - 0.1));// false
對於極大或者極小的數,能夠用科學計數法e來表示的浮點數值來表示。科學計數法容許字母e或E的後面,跟着一個整數,表示這個數值的指數部分
如下兩種狀況,javascript會自動將數值轉爲科學計數法表示
【1】小於1且小數點後面帶有6個0以上的浮點數值
0.0000003 // 3e-7 0.000003 // 0.000003
【2】整數位數字多於21位
1234567890123456789012 //1.2345678901234568e+21 1234567890123456789012.1 //1.2345678901234568e+21 123456789012345678901 //123456789012345680000
根據國際標準IEEE 754,javascript浮點數的64個二進制位,從最左邊開始,是這樣組成的
第1位: 符號位,0表示正數,1表示負數
第2位到第12位: 儲存指數部分
第13位到第64位:儲存小數部分(即有效數字)
符號位決定了一個數的正負,指數部分決定了數值的大小,小數部分決定了數值的精度
IEEE 754規定,有效數字第一位默認老是1,不保存在64位浮點數之中。也就是說,有效數字老是1.xx...xx的形式,其中xx..xx的部分保存在64位浮點數之中,最長可能爲52位
所以,javascript提供的有效數字最長爲53個二進制位
//javascript內部實際的表現形式 (-1)^符號位 * 1.xx...xx * 2^指數位
精度最長爲53個二進制位,意味着絕對值小於2的53次方的整數,即-(253-1)到253-1,均可以精確表示
Math.pow(2, 53) // 9007199254740992
因此換算成十進制,javascript數字最高精度是16位(若整數部分爲0,則表示小數點後16位;若整數部分不爲0,則表示總體保留16位)
Math.pow(2, 53)// 9007199254740992 Math.pow(2, 53) + 1// 9007199254740992 9007199254740993//9007199254740992 90071992547409921//90071992547409920 0.923456789012345678;//0.9234567890123456 9.23456789012345678;//9.234567890123456
根據標準,64位浮點數的指數部分的長度是11個二進制位,意味着指數部分的最大值是2047(211-1)。分出一半表示負數,則javascript可以表示的數值範圍爲21024到2-1023,超出這個範圍的數沒法表示
21024 = 1.79769*10308
javascript中能表示的最大值是+-1.79769*10308,而javascript能表示的最小值是+-5*10-324
javascript可以表示的整數範圍是-253到253。若是超過了此範圍的整數,沒法保證低位數字的精度
javascript中的最大值保存在Number.MAX_VALUE中,而最小值保存在Number.MIN_VALUE
console.log(Number.MIN_VALUE,Number.MAX_VALUE)//5e-324,1.7976931348623157e+308
若是數字超過最大值,javascript會返回Infinity,這稱爲正向溢出(overflow);若是等於或超過最小負值-1023(即很是接近0),javascript會直接把這個數轉爲0,這稱爲負向溢出(underflow)
以下所示,實際狀況並不是所有如此
Number.MAX_VALUE+1 === Number.MAX_VALUE;//true
當數字最大值+1時,結果並不等於Infinity,而是仍然等於最大值。這是由於精度受限,javascript中的存儲位置沒有多餘位置去存儲個位數1
當運算數和數字最大值保持在相同精度維度上時,纔可與數字最大值發生運算
Number.MAX_VALUE+1e291;//1.7976931348623157e+308 Number.MAX_VALUE+1e292;//Infinity
相似地,與數字最小值的運算也有類似狀況
Number.MIN_VALUE + 1;//1 Number.MIN_VALUE - 3e-324;//0 Number.MIN_VALUE - 2e-324;//5e-324
0.1+0.2!== 0.3
不只僅是javascript,在不少語言中0.1 + 0.2都會獲得0.30000000000000004
下面詳細解釋出現這個結果的緣由
[注意]該部份內容主要參考子遲兄的博文【0.1 + 0.2 = 0.30000000000000004】該怎樣理解?
計算機中的數字都是以二進制存儲的,若是要計算0.1 + 0.2 的結果,計算機會先把0.1和0.2分別轉化成二進制,而後相加,最後再把相加獲得的結果轉爲十進制
把10進制的0.1轉換成2進制,表示爲0.0 0011 0011...(0011循環)
(0.1).toString(2);//"0.0001100110011001100110011001100110011001100110011001101"
把10進制的0.2轉換成2進制,表示爲0.0011 0011...(0011循環)
(0.2).toString(2);//"0.001100110011001100110011001100110011001100110011001101"
因爲計算機只能保存最大53位精度,因此,用科學記數法表示
0.1的二進制爲1.1001100110011001100110011001100110011001100110011010e+4(52位小數)
0.2的二進制爲1.1001100110011001100110011001100110011001100110011010e+3(52位小數)
[注意]若是第52bit和53bit都是 1,須要進位
1.1001100110011001100110011001100110011001100110011010e-4 + 1.1001100110011001100110011001100110011001100110011010e-3 -------------------------------------------------------------------------- 0.1100110011001100110011001100110011001100110011001101e-3 + 1.1001100110011001100110011001100110011001100110011010e-3 -------------------------------------------------------------------------- 10.0110011001100110011001100110011001100110011001100111e-3 -------------------------------------------------------------------------- 1.0011001100110011001100110011001100110011001100110100e-2(52位小數) -------------------------------------------------------------------------- 0.010011001100110011001100110011001100110011001100110100 轉換爲十進制爲0.30000000000000004
javascript提供了幾個特殊數值,包括Number.MAX_VALUE、Number.MIN_VALUE、Number.POSITIVE_INFINITY、Number.NEGATIVE_INFINITY、Number.MAX_SAFE_INTEGER、Number.MIN_SAFE_INTEGER、Number.NaN、+0、-0共9個
其中,前7個特殊數值是Number對象的屬性
最值
前面已介紹過Number.MAX_VALUE表明javascript最大值,Number.MIN_VALUE表明javascript最小正值
console.log(Number.MIN_VALUE,Number.MAX_VALUE)//5e-324,1.7976931348623157e+308
Number.MAX_SAFE_INTEGER表示最大整數(253-1),Number.MIN_SAFE_INTEGER表示最小整數-(253-1)
//9007199254740991 true console.log(Number.MAX_SAFE_INTEGER,Number.MAX_SAFE_INTEGER===Math.pow(2, 53)-1) //-9007199254740991 true console.log(Number.MIN_SAFE_INTEGER,Number.MIN_SAFE_INTEGER===-(Math.pow(2, 53)-1))
Infinity
Infinity是一個全局屬性,用來存放表示無窮大的特殊數值。用for/in循環不可枚舉Infinity屬性,用delete操做符也沒法刪除它
實際上,Number.POSITIVE_INFINITY對應的是Infinity,表明正無窮;而Number.NEGATIVE_INFINITY對應的是-Infinity,表明負無窮
console.log(Number.POSITIVE_INFINITY,Number.NEGATIVE_INFINITY);//Infinity -Infinity
Infinity有正負之分
Math.pow(2,Math.pow(2,100));//Infinity 1/0;//Infinity -0/0;//-Infinity Infinity === -Infinity;//false
Infinity參與的運算結果只能是其自己、0或NaN
2 * Infinity;//Infinity 2 - Infinity;//-Infinity 2 + Infinity;//Infinity 2 / Infinity;//0 Infinity / 2;//Infinity
Infinity * Infinity;//Infinity Infinity - Infinity;//NaN Infinity + Infinity;//Infinity Infinity / Infinity;//NaN
能夠經過isFinite()來肯定一個數值是否是有窮的,包含着隱式類型轉換Number()。若是是+-Infinity或NaN時返回false,不然爲true
console.log(isFinite(Infinity))//false console.log(isFinite(NaN))//false console.log(isFinite(Number.MAX_VALUE))//true console.log(isFinite(true))//true
NaN
NaN(not a number)表示非數字,NaN與任何值都不相等,包括NaN自己,且任何涉及NaN的操做都會返回NaN
5 - 'x'; //NaN Math.acos(2); //NaN 0 / 0; //NaN
NaN == NaN;//false NaN == Infinity;//false
[NaN].indexOf(NaN);// -1 Boolean(NaN); // false
isNaN()來判斷這個數字是否是NaN,包含着隱式類型轉換Number()
console.log(isNaN(Infinity));//false console.log(isNaN(0));//false console.log(isNaN(NaN));//true console.log(isNaN('Hello'));//true
判斷NaN更可靠的方法是,利用NaN是javascript之中惟一不等於自身的值這個特色,進行判斷
function myIsNaN(value) { return value !== value; }
正負0
在javascript內部,實際上存在2個0:一個是+0,一個是-0。它們是等價的
-0 === +0;// true 0 === -0;// true 0 === +0;// true
通常地,+0和-0都會被當作0來看待,可是+0或-0看成分母,返回的值是不相等的
console.log(1/+0);//Infinity console.log(1/-0);//-Infinity console.log((1/+0) === (1/-0));//false
有3個函數能夠把非數值轉換成數值:Number()、parseInt()和parseFloat()。其中Number()能夠將任意類型的值轉化成數值,而parseInt()和parseFloat()只應用於字符串向數字的轉換
Number()
當把Number()看成一個函數來調用,而不是做爲構造器,它執行一個類型轉換。使用Number()函數能夠將任意類型的值轉化成數值
// 數值:十進制數字 console.log(Number(11),Number(011),Number(0x11));//11 9 17 // undefined:轉成 NaN Number(undefined) // NaN // null:轉成0 Number(null) // 0 // 布爾值:true 轉成1,false 轉成0 console.log(Number(true),Number(false));//1 0
Number()函數解析字符串時會識別出字符串的前置空格並去掉
【1】若字符串只包含十進制或十六進制數字,則轉成十進制的數字
[注意1]Number()不識別八進制數字的字符串,會按照十進制數字處理
[注意2]字符串'1.2.'不會報錯,但數字1.2.會報錯
【2】若字符串爲空字符串或空格字符串,則轉成0
【3】其餘狀況的字符串,則轉成NaN
console.log(Number(' 123'));//123 console.log(Number('1.2.'));//NaN console.log(Number(1.2.));//報錯 console.log(Number(''),Number(' '));//0 0 console.log(Number('11'),Number('011'),Number('0x11'));//11 11 17 console.log(Number('abc'));//NaN console.log(Number('123abc'));//NaN
Number()函數解析對象時,會按照如下步驟進行處理
【1】調用對象的valueOf()方法,若是返回原始類型的值,則直接對該值使用Number()函數
【2】若是valueOf()方法返回的仍是對象,則調用對象的toString()方法,若是返回原始類型的值,則對該值使用Number()函數
【3】若是toString()方法返回的依然是對象,則結果是NaN
在第一步中,因爲只有時間Date()對象返回的是原始類型的值數字,因此Number(new Date())返回如今到1970年1月1日00:00:00的數值類型的毫秒數
Number(new Date())//1465976459108
在第二步中,數組Array類型返回由數組中每一個值的字符串形式拼接而成的一個以逗號分隔的字符串,若是字符串中只存在數字,則返回數字,其餘狀況返回NaN;因爲其餘對象的toString()方法返回的字符串中不僅包括數字,因此返回NaN
Number([]);//0 Number([0]);//0 Number([-0]);//0 Number([10]);//10 Number([1,2]);//NaN Number(其餘對象);//NaN
parseInt()
【1】parseInt()專門用於把字符串轉換成整數。在轉換字符串時,會忽略字符串前面的空格,直到找到第一個非空格字符。若是第一個字符不是數字字符或者負號,parseInt()就會返回NaN。若是是,則繼續解析,直到解析完成或者遇到非數字字符
console.log(parseInt(' 123.8px'));//123 console.log(parseInt(' 123.8 '));//123 console.log(parseInt(' -123.8px'));//-123 console.log(parseInt('a123.8px'));//NaN console.log(parseInt('0 123.8px'));//0
【2】parseInt()能夠識別出各類進制的數字,輸出的是運算後的十進制的數字,如1.0或1.或01會以1輸出。在解析八進制字面量的字符串,ECMAScript3會解析八進制,但ECMAScript5沒有解析八進制的能力
console.log(parseInt('11'));//11 console.log(parseInt(11));//11 console.log(parseInt('11.1'));//11 console.log(parseInt(11.1));//11 console.log(parseInt('011'));//11 console.log(parseInt(011));//9 console.log(parseInt('011.1'));//11 console.log(parseInt(011.1));//報錯 console.log(parseInt('0x11'));//17 console.log(parseInt(0x11));//17 console.log(parseInt('0x11.1'));//17 console.log(parseInt(0x11.1));//報錯
[注意]對於那些會自動轉爲科學計數法的數字,parseInt會將科學計數法的表示方法視爲字符串,所以致使一些奇怪的結果
console.log(parseInt(1000000000000000000000.5)); // 1 // 等同於 console.log(parseInt('1e+21')); // 1 console.log(parseInt(0.0000008)); // 8 // 等同於 console.log(parseInt('8e-7')); // 8
【3】parseInt()
方法還能夠接受第二個參數(2到36之間),表示被解析的值的進制,返回該值對應的十進制數。默認狀況下,parseInt
的第二個參數爲10,即默認是十進制轉十進制
console.log(parseInt('11',2));//3 console.log(parseInt('11',8));//9 console.log(parseInt('11',10));//11 console.log(parseInt('11',16));//17
若是第二個參數不是數值,會被自動轉爲一個整數。這個整數只有在2到36之間,才能獲得有意義的結果,超出這個範圍,則返回NaN。若是第二個參數是0、undefined和null,則直接忽略
console.log(parseInt('10', 37)); // NaN console.log(parseInt('10', 1)); // NaN console.log(parseInt('10', 0)); // 10 console.log(parseInt('10', null)); // 10 console.log(parseInt('10', undefined)); // 10
若是字符串包含對於指定進制無心義的字符,則從最高位開始,只返回能夠轉換的數值。若是最高位沒法轉換,則直接返回NaN
console.log(parseInt('1546', 2)); // 1 console.log(parseInt('546', 2)); // NaN
【4】parseInt()是專門用來處理字符串轉換數字的,parseInt處理非字符串和數字類型時輸出NaN。可是,實際上parseInt()包含着隱式的toString()方法,因此parseInt([數字或字符串])輸出對應的數字
console.log(parseInt(null),parseInt(undefined));//NaN NaN console.log(parseInt(true),parseInt(false));//NaN NaN console.log(parseInt([]),parseInt(['2.5px']),parseInt([2.5]));//NaN 2 2 console.log(parseInt(''),parseInt(' '),parseInt({}));//NaN NaN NaN
parseFloat()
【1】parseFloat()專門用於字符串轉換浮點數。一樣地,解析時會忽略字符串前面的空格,直到找到第一個非空格字符,而後一直解析到字符串末尾或一個無效的浮點數字字符爲止
console.log(parseFloat(' 0123.px'));//123 console.log(parseFloat(' 123.px'));//123 console.log(parseFloat(' 123.1px'));//123.1 console.log(parseFloat(' 123.1.2px '));//123.1 console.log(parseFloat(' -123.0px'));//-123 console.log(parseFloat('.123.1px'));//0.123 console.log(parseFloat('0 123px'));//0
[注意]若是字符串符合科學計數法,則會進行相應的轉換
console.log(parseFloat('314e-2')); // 3.14 console.log(parseFloat('0.0314E+2')); // 3.14
【2】parseFloat()能夠識別不一樣進制的數字,但只能解析十進制字符串
console.log(parseFloat('11'));//11 console.log(parseFloat(11));//11 console.log(parseFloat('11.1'));//11.1 console.log(parseFloat(11.1));//11.1 console.log(parseFloat('011'));//11 console.log(parseFloat(011));//9 console.log(parseFloat('011.1'));//11.1 console.log(parseFloat(011.1));//報錯 console.log(parseFloat('0x11'));//0 console.log(parseFloat(0x11));//17 console.log(parseFloat('0x11.1'));//0 console.log(parseFloat(0x11.1));//報錯
【3】parseFloat()是專門用來處理字符串轉換浮點數的,parseFloat處理非字符串和數字類型時輸出NaN。可是,實際上parseFloat()包含着隱式的toString()方法,因此parseFloat([數字或字符串])輸出對應的數字
console.log(parseFloat(null),parseFloat(undefined));//NaN NaN console.log(parseFloat(true),parseFloat(false));//NaN NaN console.log(parseFloat([]),parseFloat([2.1]),parseFloat(['2.1px']));//NaN 2.1 2.1 console.log(parseFloat(''),parseFloat({}));//NaN NaN
[注意]Number('')的結果是0,parseInt('')和parseFloat('')的結果是NaN
關於Number()對象的實例方法總共有6個,分爲兩類。包括toString()、toLocalString()、valueOf()這3種對象通用方法和toFixed()、toExponential()、toPrecision()這3種改變數值顯示形式並轉換爲字符串的方法
valueOf()方法返回對象的數字字面量
toString()方法將數字轉換爲字符串
toLocalString()方法將數字轉換爲本地慣例格式化數字的字符串
console.log(typeof 1.1.valueOf(),1.1.valueOf());//number 1.1 console.log(typeof 1.1.toString(),1.1.toString());//String '1.1' console.log(typeof 1.1.toLocaleString(),1.1.toLocaleString());//String '1.1'
[注意]若是數字不加括號,點會被javascript引擎解釋成小數點,從而報錯
console.log(typeof 1.valueOf(),1.valueOf());//報錯 console.log(typeof 1.toString(),1.toString());//報錯 console.log(typeof 1.toLocaleString(),1.toLocaleString());//報錯
console.log(typeof (1).valueOf(),(1).valueOf());//number 1 console.log(typeof (1).toString(),(1).toString());//String '1' console.log(typeof (1).toLocaleString(),(1).toLocaleString());//String '1'
除了爲數字加上括號,還能夠在數字後面加兩個點,javascript會把第一個點理解成小數點,把第二個點理解成調用對象屬性,從而獲得正確結果
console.log(10..toString()); // "10" console.log(10 .toString()); // "10" console.log(10.0.toString()); // "10"
toString()方法能夠接受一個參數,該參數應當是2到36之間的整數,表示輸出的進制。若是該參數不存在,或者爲undefined,默認將數值先轉爲十進制,再輸出字符串
var num = 10; console.log(num.toString());//'10' console.log(num.toString(2));//'1010' console.log(num.toString(8));//'12' console.log(num.toString(10));//'10' console.log(num.toString(16));//'a' console.log(num.toString(undefined));//'10'
若是參數超出2-36的範圍,或者爲其餘值時,報錯
console.log((10).toString(0));//報錯 console.log((10).toString(null));//報錯
toFixed()
toFixed()方法按照指定的小數位返回數值四捨五入後的字符串表示(經常使用於處理貨幣值)
[注意]toFixed()裏的參數只接受0-20,若不傳參或參數爲undefined則至關於參數是0
var num = 10.456; console.log(num.toFixed(2));//'10.46' console.log(num.toFixed());//'10' console.log(num.toFixed(0));//'10' console.log(num.toFixed(undefined));//'10' console.log(num.toFixed(-1));//報錯
toExponential()
toExponential()方法返回數值四捨五入後的指數表示法(e表示法)的字符串表示,參數表示轉換後的小數位數
[注意]toExponential()方法裏的參數只接受0-20,但與toFxied()不一樣的是,若不傳參或參數爲undefined,則保留儘量多的有效數字;若參數是0表示沒有小數部分
var num = 10.456; console.log(num.toExponential(2));//'1.05e+1' console.log(num.toExponential());//'1.0456e+1' console.log(num.toExponential(0));//'1e+1' console.log(num.toExponential(undefined));//'1.0456e+1' console.log(num.toExponential(-1));//報錯
toPrecision()
toPrecision()方法接收一個參數,即表示數值的全部數字的位數(不包括指數部分),自動調用toFixed()或toExponential()
[注意]toPrecision()裏的參數只接受1-21,若不傳參或參數爲undefined則至關於調用toString()方法
var num = 10.1; console.log(num.toPrecision(3));//'10.1' console.log(num.toPrecision(2));//'10' console.log(num.toPrecision(1));//'1e+1' console.log(num.toPrecision());//'10.1' console.log(num.toPrecision(undefined));//'10.1' console.log(num.toPrecision(0));//報錯
[注意]toFixed()、toExponential()、toPrecision()這三個方法在小數位用於四捨五入時都不太可靠,跟浮點數不是精確儲存有關
console.log((12.25).toPrecision(3)); // "12.3" console.log((12.25).toFixed(1)); // "12.3" console.log((12.25).toExponential(2)); // "1.23e+1" console.log((12.35).toPrecision(3)); // "12.3" console.log((12.35).toFixed(1)); // "12.3" console.log((12.35).toExponential(2)); // "1.23e+1"
【1】 ES5/類型 https://www.w3.org/html/ig/zh/wiki/ES5/types#Number_.E7.B1.BB.E5.9E.8B ES5/ ES5/標準內置對象 https://www.w3.org/html/ig/zh/wiki/ES5/builtins#Number_.E5.AF.B9.E8.B1.A1
【2】 阮一峯Javascript標準參考教程——基本語法之數值http://javascript.ruanyifeng.com/grammar/number.html 標準庫Number對象http://javascript.ruanyifeng.com/stdlib/number.html
【3】 W3School-Javascript高級教程——ECMAScript原始類型 http://www.w3school.com.cn/js/pro_js_primitivetypes.asp【4】《javascript權威指南(第6版)》第3章 類型、值和變量【5】《javascript高級程序設計(第3版)》第3章 基本概念 第5章 引用類型【6】《javascript語言精粹(修訂版)》第2章 語法 第8章 方法【7】《javascript DOM編程藝術(第2版)》第2章 Javascript語法【8】《javascript啓示錄》 第11章 Number()