W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
JavaScript內(nèi)部,所有數(shù)字都是以64位浮點(diǎn)數(shù)形式儲(chǔ)存,即使整數(shù)也是如此。所以,1與1.0是相等的,而且1加上1.0得到的還是一個(gè)整數(shù),不會(huì)像有些語(yǔ)言那樣變成小數(shù)。
1 === 1.0 // true
1 + 1.0 // 2
由于浮點(diǎn)數(shù)不是精確的值,所以涉及小數(shù)的比較和運(yùn)算要特別小心。
0.1 + 0.2 === 0.3
// false
0.3 / 0.1
// 2.9999999999999996
(0.3-0.2) === (0.2-0.1)
// false
根據(jù)國(guó)際標(biāo)準(zhǔn)IEEE 754,64位浮點(diǎn)數(shù)格式的64個(gè)二進(jìn)制位中,第0位到第51位儲(chǔ)存有效數(shù)字部分,第52到第62位儲(chǔ)存指數(shù)部分,第63位是符號(hào)位,0表示正數(shù),1表示負(fù)數(shù)。
因此,JavaScript提供的有效數(shù)字的精度為53個(gè)二進(jìn)制位(IEEE 754規(guī)定有效數(shù)字第一位默認(rèn)為1,再加上后面的52位),也就是說(shuō),絕對(duì)值小于等于2的53次方的整數(shù)都可以精確表示。
Math.pow(2, 53) // 54個(gè)二進(jìn)制位
// 9007199254740992
Math.pow(2, 53) + 1
// 9007199254740992
Math.pow(2, 53) + 2
// 9007199254740994
Math.pow(2, 53) + 3
// 9007199254740996
Math.pow(2, 53) + 4
// 9007199254740996
從上面示例可以看到,大于2的53次方以后,整數(shù)運(yùn)算的結(jié)果開始出現(xiàn)錯(cuò)誤。所以,大于等于2的53次方的數(shù)值,都無(wú)法保持精度。
Math.pow(2, 53)
// 9007199254740992
9007199254740992111
// 9007199254740992000
上面示例表明,大于2的53次方以后,多出來(lái)的有效數(shù)字(最后三位的111)都會(huì)無(wú)法保存,變成0。
另一方面,64位浮點(diǎn)數(shù)的指數(shù)部分的長(zhǎng)度是11個(gè)二進(jìn)制位,意味著指數(shù)部分的最大值是2047(2的11次方減1)。也就是說(shuō),64位浮點(diǎn)數(shù)的指數(shù)部分的值最大為2047,分出一半表示負(fù)數(shù),則JavaScript能夠表示的數(shù)值范圍為21024到2-1023(開區(qū)間),超出這個(gè)范圍的數(shù)無(wú)法表示。
如果指數(shù)部分等于或超過(guò)最大正值1024,JavaScript會(huì)返回Infinity(關(guān)于Infinity的介紹參見(jiàn)下文),這稱為“正向溢出”;如果等于或超過(guò)最小負(fù)值-1023(即非常接近0),JavaScript會(huì)直接把這個(gè)數(shù)轉(zhuǎn)為0,這稱為“負(fù)向溢出”。事實(shí)上,JavaScript對(duì)指數(shù)部分的兩個(gè)極端值(11111111111和00000000000)做了定義,11111111111表示NaN和Infinity,00000000000表示0。
var x = 0.5;
for(var i =0;i<25;i++) x = x*x;
x // 0
上面代碼對(duì)0.5連續(xù)做25次平方,由于最后結(jié)果太接近0,超出了可表示的范圍,JavaScript就直接將其轉(zhuǎn)為0。
至于具體的最大值和最小值,JavaScript提供Number對(duì)象的MAX_VALUE和MIN_VALUE屬性表示(參見(jiàn)《Number對(duì)象》一節(jié))。
Number.MAX_VALUE // 1.7976931348623157e+308
Number.MIN_VALUE // 5e-324
JavaScript的數(shù)值有多種表示方法,可以用字面形式直接表示,也可以采用科學(xué)計(jì)數(shù)法表示,下面是兩個(gè)科學(xué)計(jì)數(shù)法的例子。
123e3 // 123000
123e-3 // 0.123
以下兩種情況,JavaScript會(huì)自動(dòng)將數(shù)值轉(zhuǎn)為科學(xué)計(jì)數(shù)法表示,其他情況都采用字面形式直接表示。
(1)小數(shù)點(diǎn)前的數(shù)字多于21位。
1234567890123456789012
// 1.2345678901234568e+21
123456789012345678901
// 123456789012345680000
(2)小數(shù)點(diǎn)后的零多于5個(gè)。
0.0000003 // 3e-7
0.000003 // 0.000003
正常情況下,所有數(shù)值都為十進(jìn)制。如果要表示十六進(jìn)制的數(shù),必須以0x或0X開頭,比如十進(jìn)制的255等于十六進(jìn)制的0xff或0Xff。如果要表示八進(jìn)制數(shù),必須以0開頭,比如十進(jìn)制的255等于八進(jìn)制的0377。由于八進(jìn)制表示法的前置0,在處理時(shí)很容易造成混亂,有時(shí)為了區(qū)分一個(gè)數(shù)到底是八進(jìn)制還是十進(jìn)制,會(huì)增加很大的麻煩,所以建議不要使用這種表示法。
JavaScript提供幾個(gè)特殊的數(shù)值。
嚴(yán)格來(lái)說(shuō),JavaScript提供零的三種寫法:0、+0、-0。它們是等價(jià)的。
-0 === +0 // true
0 === -0 // true
0 === +0 // true
但是,如果正零和負(fù)零分別當(dāng)作分母,它們返回的值是不相等的。
(1/+0) === (1/-0) // false
上面代碼之所以出現(xiàn)這樣結(jié)果,是因?yàn)槌哉愕玫?Infinity,除以負(fù)零得到-Infinity,這兩者是不相等的(關(guān)于Infinity詳見(jiàn)后文)。
(1)含義
NaN是JavaScript的特殊值,表示“非數(shù)字”(Not a Number),主要出現(xiàn)在將字符串解析成數(shù)字出錯(cuò)的場(chǎng)合。
5 - 'x'
// NaN
上面代碼運(yùn)行時(shí),會(huì)自動(dòng)將字符串“x”轉(zhuǎn)為數(shù)值,但是由于x不是數(shù)字,所以最后得到結(jié)果為NaN,表示它是“非數(shù)字”(NaN)。
另外,一些數(shù)學(xué)函數(shù)的運(yùn)算結(jié)果會(huì)出現(xiàn)NaN。
Math.acos(2) // NaN
Math.log(-1) // NaN
Math.sqrt(-1) // NaN
0除以0也會(huì)得到NaN。
0 / 0 // NaN
需要注意的是,NaN不是一種獨(dú)立的數(shù)據(jù)類型,而是一種特殊數(shù)值,它的數(shù)據(jù)類型依然屬于Number,使用typeof運(yùn)算符可以看得很清楚。
typeof NaN // 'number'
(2)運(yùn)算規(guī)則
NaN不等于任何值,包括它本身。
NaN === NaN // false
由于數(shù)組的indexOf方法,內(nèi)部使用的是嚴(yán)格相等運(yùn)算符,所以該方法對(duì)NaN不成立。
[NaN].indexOf(NaN) // -1
NaN在布爾運(yùn)算時(shí)被當(dāng)作false。
Boolean(NaN) // false
NaN與任何數(shù)(包括它自己)的運(yùn)算,得到的都是NaN。
NaN + 32 // NaN
NaN - 32 // NaN
NaN * 32 // NaN
NaN / 32 // NaN
(3)判斷NaN的方法
isNaN方法可以用來(lái)判斷一個(gè)值是否為NaN。
isNaN(NaN) // true
isNaN(123) // false
但是,isNaN只對(duì)數(shù)值有效,如果傳入其他值,會(huì)被先轉(zhuǎn)成數(shù)值。比如,傳入字符串的時(shí)候,字符串會(huì)被先轉(zhuǎn)成NaN,所以最后返回true,這一點(diǎn)要特別引起注意。也就是說(shuō),isNaN為true的值,有可能不是NaN,而是一個(gè)字符串。
isNaN("Hello") // true
// 相當(dāng)于
isNaN(Number("Hello")) // true
出于同樣的原因,對(duì)于數(shù)組和對(duì)象,isNaN也返回true。
isNaN({}) // true
isNaN(Number({})) // true
isNaN(["xzy"]) // true
isNaN(Number(["xzy"])) // true
因此,使用isNaN之前,最好判斷一下數(shù)據(jù)類型。
function myIsNaN(value) {
return typeof value === 'number' && isNaN(value);
}
判斷NaN更可靠的方法是,利用NaN是JavaScript之中唯一不等于自身的值這個(gè)特點(diǎn),進(jìn)行判斷。
function myIsNaN(value) {
return value !== value;
}
(1)定義
Infinity表示“無(wú)窮”。除了0除以0得到NaN,其他任意數(shù)除以0,得到Infinity。
1 / -0 // -Infinity
1 / +0 // Infinity
上面代碼表示,非0值除以0,JavaScript不報(bào)錯(cuò),而是返回Infinity。這是需要特別注意的地方。
Infinity有正負(fù)之分。
Infinity === -Infinity // false
Math.pow(+0, -1) // Infinity
Math.pow(-0, -1) // -Infinity
運(yùn)算結(jié)果超出JavaScript可接受范圍,也會(huì)返回?zé)o窮。
Math.pow(2, 2048) // Infinity
-Math.pow(2, 2048) // -Infinity
由于數(shù)值正向溢出(overflow)、負(fù)向溢出(underflow)和被0除,JavaScript都不報(bào)錯(cuò),所以單純的數(shù)學(xué)運(yùn)算幾乎沒(méi)有可能拋出錯(cuò)誤。
(2)運(yùn)算規(guī)則
Infinity的四則運(yùn)算,符合無(wú)窮的數(shù)學(xué)計(jì)算規(guī)則。
Infinity + Infinity // Infinity
5 * Infinity // Infinity
5 - Infinity // -Infinity
Infinity / 5 // Infinity
5 / Infinity // 0
Infinity減去或除以Infinity,得到NaN。
Infinity - Infinity // NaN
Infinity / Infinity // NaN
Infinity可以用于布爾運(yùn)算??梢杂涀?,Infinity是JavaScript中最大的值(NaN除外),-Infinity是最小的值(NaN除外)。
5 > -Infinity // true
5 > Infinity // false
(3)isFinite函數(shù)
isFinite函數(shù)返回一個(gè)布爾值,檢查某個(gè)值是否為正常值,而不是Infinity。
isFinite(Infinity) // false
isFinite(-1) // true
isFinite(true) // true
isFinite(NaN) // false
上面代碼表示,如果對(duì)NaN使用isFinite函數(shù),也返回false,表示NaN不是一個(gè)正常值。
parseInt方法可以將字符串或小數(shù)轉(zhuǎn)化為整數(shù)。如果字符串頭部有空格,空格會(huì)被自動(dòng)去除。
parseInt("123") // 123
parseInt(1.23) // 1
parseInt(' 81') // 81
如果字符串包含不能轉(zhuǎn)化為數(shù)字的字符,則不再進(jìn)行轉(zhuǎn)化,返回已經(jīng)轉(zhuǎn)好的部分。
parseInt("8a") // 8
parseInt("12**") // 12
parseInt("12.34") // 12
如果字符串的第一個(gè)字符不能轉(zhuǎn)化為數(shù)字(正負(fù)號(hào)除外),返回NaN。
parseInt("abc") // NaN
parseInt(".3") // NaN
parseInt("") // NaN
parseInt方法還可以接受第二個(gè)參數(shù)(2到36之間),表示被解析的值的進(jìn)制。
parseInt(1000, 2) // 8
parseInt(1000, 6) // 216
parseInt(1000, 8) // 512
這意味著,可以用parseInt方法進(jìn)行進(jìn)制的轉(zhuǎn)換。
parseInt("1011", 2) // 11
需要注意的是,如果第一個(gè)參數(shù)是數(shù)值,則會(huì)將這個(gè)數(shù)值先轉(zhuǎn)為10進(jìn)制,然后再應(yīng)用第二個(gè)參數(shù)。
parseInt(010, 10) // 8
parseInt(010, 8) // NaN
parseInt(020, 10) // 16
parseInt(020, 8) // 14
上面代碼中,010會(huì)被先轉(zhuǎn)為十進(jìn)制8,然后再應(yīng)用第二個(gè)參數(shù),由于八進(jìn)制中沒(méi)有8這個(gè)數(shù)字,所以parseInt(010, 8)會(huì)返回NaN。同理,020會(huì)被先轉(zhuǎn)為十進(jìn)制16,然后再應(yīng)用第二個(gè)參數(shù)。
如果第一個(gè)參數(shù)是字符串,則不會(huì)將其先轉(zhuǎn)為十進(jìn)制。
parseInt("010") // 10
parseInt("010",10) // 10
parseInt("010",8) // 8
可以看到,parseInt的很多復(fù)雜行為,都是由八進(jìn)制的前綴0引發(fā)的。因此,ECMAScript 5不再允許parseInt將帶有前綴0的數(shù)字,視為八進(jìn)制數(shù)。但是,為了保證兼容性,大部分瀏覽器并沒(méi)有部署這一條規(guī)定。
另外,對(duì)于那些會(huì)自動(dòng)轉(zhuǎn)為科學(xué)計(jì)數(shù)法的數(shù)字,parseInt會(huì)出現(xiàn)一些奇怪的錯(cuò)誤。
parseInt(1000000000000000000000.5, 10) // 1
// 等同于
parseInt('1e+21', 10) // 1
parseInt(0.0000008, 10) // 8
// 等同于
parseInt('8e-7', 10) // 8
parseFloat方法用于將一個(gè)字符串轉(zhuǎn)為浮點(diǎn)數(shù)。
如果字符串包含不能轉(zhuǎn)化為浮點(diǎn)數(shù)的字符,則不再進(jìn)行轉(zhuǎn)化,返回已經(jīng)轉(zhuǎn)好的部分。
parseFloat("3.14");
parseFloat("314e-2");
parseFloat("0.0314E+2");
parseFloat("3.14more non-digit characters");
上面四個(gè)表達(dá)式都返回3.14。
parseFloat方法會(huì)自動(dòng)過(guò)濾字符串前導(dǎo)的空格。
parseFloat("\t\v\r12.34\n ")
// 12.34
如果第一個(gè)字符不能轉(zhuǎn)化為浮點(diǎn)數(shù),則返回NaN。
parseFloat("FF2") // NaN
parseFloat("") // NaN
上面代碼說(shuō)明,parseFloat將空字符串轉(zhuǎn)為NaN。
這使得parseFloat的轉(zhuǎn)換結(jié)果不同于Number函數(shù)。
parseFloat(true) // NaN
Number(true) // 1
parseFloat(null) // NaN
Number(null) // 0
parseFloat('') // NaN
Number('') // 0
parseFloat('123.45#') // 123.45
Number('123.45#') // NaN
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: