99re热这里只有精品视频,7777色鬼xxxx欧美色妇,国产成人精品一区二三区在线观看,内射爽无广熟女亚洲,精品人妻av一区二区三区

聊聊JavaScript中的二進(jìn)制數(shù)

2018-06-17 11:07 更新

事情的起因是這樣的最近在業(yè)務(wù)代碼中發(fā)現(xiàn)下面這樣的一行代碼,我看了半天沒(méi)搞明白是什么意思,不知道聰明的你能不能知道是什么意思呢?

!~location.href.search('***')

如果你也不知道,并且也像我一樣富有好奇心那么就和我一起來(lái)學(xué)習(xí)這篇文章吧。在本文中你將學(xué)到如下知識(shí):

  • 二進(jìn)制數(shù)的表示
  • js中的二進(jìn)制數(shù)整數(shù)
  • js中的位運(yùn)算

二進(jìn)制數(shù)

本文假設(shè)你知道計(jì)算機(jī)中用二進(jìn)制數(shù)來(lái)存儲(chǔ),計(jì)算數(shù)字,并且熟悉二進(jìn)制數(shù)的表示方法。

為了實(shí)現(xiàn)不同的目的,其實(shí)都是為了簡(jiǎn)化問(wèn)題,二進(jìn)制數(shù)在計(jì)算機(jī)中有不同的表示方法,如原碼、反碼、補(bǔ)碼和移碼等。

注意:本文問(wèn)了簡(jiǎn)化運(yùn)算,二進(jìn)制數(shù)都是用一個(gè)字節(jié)——8個(gè)二進(jìn)制位來(lái)簡(jiǎn)化說(shuō)明

先來(lái)說(shuō)說(shuō)真值吧,我們表示自然數(shù)包括正數(shù),負(fù)數(shù)和0,下面是1和-1的二進(jìn)制表示,我們稱為真值

+ 00000001 # +1
- 00000001 # -1

8位二進(jìn)制數(shù)能表示的真值范圍是[-2^8, +2^8]。

由于計(jì)算機(jī)只能存儲(chǔ)0和1,不能存儲(chǔ)正負(fù),所以用8個(gè)二進(jìn)制位的最高位來(lái)表示符號(hào),0表示正,1表示負(fù),用后七位來(lái)表示真值的絕對(duì)值,這種表示方法稱為原碼表示法,簡(jiǎn)稱原碼,上面的1和-1的原碼如下:

0 0000001 # +1
1 0000001 # -1

由于10000000的意思是-0,這個(gè)沒(méi)有意義,所有這個(gè)數(shù)字被用來(lái)表示-128,所有負(fù)數(shù)就比整數(shù)多一個(gè)。

由于最高位被用來(lái)表示符號(hào)了,現(xiàn)在能表示的范圍是[-2^7, +2^7-1],即[-128, +127]

反碼是另一種表示數(shù)字的方法,其規(guī)則是整數(shù)的反碼何其原碼一樣,負(fù)數(shù)的反碼將其原碼的符號(hào)位不變,其余各位按位取反

0 0000001 # +1
1 1111110 # -1

反碼的表示范圍是[-2^7, +2^7-1],即[-128, +127]

補(bǔ)碼是另外一種表示方法,主要是為了簡(jiǎn)化運(yùn)算,將減法變?yōu)榧臃ǘl(fā)明的數(shù)字表示法,其規(guī)則是整數(shù)的補(bǔ)碼和原碼一樣,負(fù)數(shù)的補(bǔ)碼是其反碼末尾加1

0 0000001 # +1
1 1111111 # -1

快速計(jì)算負(fù)數(shù)補(bǔ)碼的規(guī)則就是,由其原碼低位向高位找到第一個(gè)1,1和其低位不變,1前面的高位按位取反即可,不知道聰明的你能不能想到原理。

8位補(bǔ)碼表示的范圍是[-2^7, +2^7-1],即[-128, +127]

js中的二進(jìn)制數(shù)整數(shù)

再來(lái)說(shuō)說(shuō)js中的二進(jìn)制整數(shù)表示,一名合格的jser應(yīng)該支持在js中只有一種數(shù)字類型,就是浮點(diǎn)型,js的浮點(diǎn)數(shù)遵循IEEE 754規(guī)范,如果你想了解js浮點(diǎn)數(shù)的更多知識(shí),我推薦你看這篇文章《每一個(gè)JavaScript開(kāi)發(fā)者應(yīng)該了解的浮點(diǎn)知識(shí)》。

然而在js中還有另一種類型的數(shù)據(jù),那就是用32個(gè)比特位表示的整數(shù),只要對(duì)js中的任何數(shù)字做位運(yùn)算操作系統(tǒng)內(nèi)部都會(huì)將其轉(zhuǎn)換成整形,嘗試在控制臺(tái)輸入下面的代碼

2.1 | 0 # 或運(yùn)算
>>> 2

js中的這種整形是區(qū)分正負(fù)數(shù)的,我們根據(jù)上面的知識(shí)推斷js中的整數(shù)的表示范圍是[-2^31, +2^31-1],即[-2147483648, +2147483647],在控制臺(tái)輸出下面的代碼來(lái)驗(yàn)證我們的推斷

-2147483648 | 0
>>> -2147483648

-2147483649 | 0
>>> 2147483647

2147483647 | 0
>>> 2147483647

2147483648 | 0
>>> -2147483648

從上面的結(jié)果可以看出,大于和小于最低和最高的值再去進(jìn)行轉(zhuǎn)換時(shí)都將改變正負(fù)號(hào)

js中的位運(yùn)算

js中的位運(yùn)算符有下面這些,對(duì)數(shù)字進(jìn)行這些操作時(shí),系統(tǒng)內(nèi)部都會(huì)講64的浮點(diǎn)數(shù)轉(zhuǎn)換成32位的整形

  • & 與
  • | 或
  • ~ 非
  • ^ 異或
  • << 左移
  • >> 算數(shù)右移(有符號(hào)右移)
  • >>> 邏輯右移(無(wú)符號(hào)右移)

下面舉例子來(lái)說(shuō)明每個(gè)運(yùn)算符的作用,開(kāi)始之前先來(lái)介紹幾個(gè)會(huì)用到的知識(shí)點(diǎn)

原生二進(jìn)制字面量

es6中引入了原生二進(jìn)制字面量,二進(jìn)制數(shù)的語(yǔ)法是0b開(kāi)頭,我們將會(huì)用到這個(gè)新功能,目前chrome最新版已經(jīng)支持。

0b111 // 7
0b001 // 1

Number.prototype.toString

先來(lái)介紹下下面會(huì)用到的一個(gè)方法——Number.prototype.toString方法可以講數(shù)字轉(zhuǎn)化為字符串,有一個(gè)可選的參數(shù),用來(lái)決定將數(shù)字顯示為指定的進(jìn)制,下面可以查看3的二進(jìn)制表示,根據(jù)這個(gè)特性,我還特意做了一個(gè)進(jìn)制轉(zhuǎn)化工具

3..toString(2)
>> 11

& 與

&按位與會(huì)將操作數(shù)和被操作數(shù)的相同為進(jìn)行與運(yùn)算,如果都為1則為1,如果有一個(gè)為0則為0

101
011
---
001

101和011與完的結(jié)果就是001,下面在js中進(jìn)行驗(yàn)證

(0b101 & 0b011).toString(2)
>>> "1"

| 或

|按位或是相同的位置上只要有一個(gè)為1就是1,兩個(gè)都為0則為0

101
001
---
101

101和001或完的結(jié)果是101,下面在js中進(jìn)行驗(yàn)證

(0b101 | 0b001).toString(2)
>>> "101"

~ 非

~操作符會(huì)將操作數(shù)的每一位取反,如果是1則變?yōu)?,如果是0則邊為1

101
---
010

101按位非的結(jié)果是010,下面在js中驗(yàn)證

(~0b101).toString(2)
>>> "-110"

啊呀,怎么結(jié)果不對(duì)呢?。?!上面提到了js中的數(shù)字是有符號(hào)的,我們忘記了最高位的符號(hào)了,為了簡(jiǎn)化我們將32位簡(jiǎn)化為8位,注意最高位是符號(hào)位

0 0000101
1 1111010 // 非后的結(jié)果
1 0000101 // 求反
1 0000110 // 求補(bǔ)

1 1111010明顯是一個(gè)負(fù)數(shù),而且是負(fù)數(shù)的補(bǔ)碼表示,我們的求它的原碼,也就是再對(duì)它求補(bǔ)1 0000110就是這個(gè)數(shù)的真值,也就是結(jié)果顯示-110,這下總算自圓其說(shuō)了,O(∩_∩)O哈哈~

其實(shí)上面的與和或也都是會(huì)操作符號(hào)位的,不信你試試下面這兩個(gè),可以看到符號(hào)位都參與了運(yùn)算

(0b1&-0b1)
>>> 1

(0b1|-0b1)
>>> -1

^ 異或

再來(lái)說(shuō)說(shuō)異或,這個(gè)比較有意思,異或顧名思義看看兩個(gè)位是否為異——不同,兩個(gè)位不同則為1,兩個(gè)位相同則為0

101
001
---
100

101和001異或的結(jié)果是100,js中驗(yàn)證

(0b101^0b001).toString(2)
>>> "100"

<< 左移

左移的規(guī)則就是每一位都向左移動(dòng)一位,末尾補(bǔ)0,其效果相當(dāng)于×2,其實(shí)計(jì)算機(jī)就是用移位操作來(lái)計(jì)算乘法的

010
---
0100

010左移一位就會(huì)變?yōu)?00,下面在js中驗(yàn)證

(0b010<<1).toString(2)
>>> "100"

>> 算數(shù)右移(有符號(hào)右移)

算數(shù)右移也稱為有符號(hào)右移,也就是移位的時(shí)候高位補(bǔ)的是其符號(hào)位,整數(shù)則補(bǔ)0,負(fù)數(shù)則補(bǔ)1

(0b111>>1).toString(2)
>>> "11"

(-0b111>>1).toString(2)
>>> "-100"

負(fù)數(shù)的結(jié)果好像不太對(duì)勁,我們來(lái)看看是怎么回事

-111 // 真值
1 0000111 // 原碼
1 1111001 // 補(bǔ)碼
1 1111100 // 算數(shù)右移
1 0000100 // 移位后的原碼
-100 // 移位后的真值

>>> 邏輯右移(無(wú)符號(hào)右移)

邏輯右移又稱為無(wú)符號(hào)右移,也就是右移的時(shí)候高位始終補(bǔ)0,對(duì)于整數(shù)和算數(shù)右移沒(méi)有區(qū)別

(0b111>>>1).toString(2)
>>> "11"

對(duì)于負(fù)數(shù)則就不同了,右移后會(huì)變?yōu)檎龜?shù)

(-0b111>>>1).toString(2)
>>> "1111111111111111111111111111100"

關(guān)于開(kāi)頭的問(wèn)題

關(guān)于二進(jìn)制數(shù)就說(shuō)這么多吧,再來(lái)說(shuō)說(shuō)開(kāi)頭的問(wèn)題,開(kāi)頭的問(wèn)題其實(shí)可以分解為下面的問(wèn)題因?yàn)閟earch會(huì)返回-1 和找到位置的索引,也就成了下面的問(wèn)題

!~-1
>>> ture

!~0
>>> false

!~1
>>> false

非運(yùn)算對(duì)于數(shù)字的結(jié)果相當(dāng)于改變符號(hào),并對(duì)其值的絕對(duì)值-1

~-1
>>> 0

~0
>>> -1

~1
>>> -2

其實(shí)可以看出!~x的邏輯就是判斷x是否為-1,my god這邏輯真是逆天了,我還是勸大家直接寫(xiě)成 x === -1多好啊

總結(jié)

通過(guò)這篇文章終于把當(dāng)年沒(méi)學(xué)明白的二進(jìn)制數(shù)搞明白了,希望你和我一樣,祝你好運(yùn)。

參考資料

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)