按位操做符

位運算在算法中頗有用,速度能夠比四則運算快不少。算法

To2orTo10

JS中十進制轉二進制: (val).toString(2)
JS中二進制轉十進制: parseInt(val, 2)安全

JS中規定安全整數的範圍是-2^53~2^53,因此大於9007199254740991的數進制轉換會存在精度問題spa

讀取的十進制是根據原碼來讀取,而在內存中,數值都是以二進制補碼形式保存的code

十進制-5的二進制表示爲:1000,0101(原碼)
原碼除符號位外,所有取反再+1:11111011(補碼,內存存儲形式)blog

~-5的結果:
clipboard.png索引

  • 正數的補碼和原碼同樣
  • 負數原碼補碼轉換規則:
    符號位不動,從低位往高位數,遇到第一個1以前,包括第一個1不做任何取反,以後,每位都取反。避免了原碼轉反碼再轉補碼的繁瑣。ip

    1. {原碼符號位不變} + {數值位按位取反後+1}
    2. {原碼符號位不變} + {數值位從右邊數第一個1及其右邊的0保持不變,左邊安位取反}
// 7
00000111 // 原碼
00000111 // 補碼

// -6
10000110 // 原碼
11111010 // 補碼 // {原碼符號位不變} + {數值位從右邊數第一個1及其右邊的0保持不變,左邊安位取反}

// -6
10000110 // 原碼
11111001 // 反碼
11111010 // 補碼 // {原碼符號位不變} + {數值位按位取反後+1}

進行按位操做,都是針對補碼去操做內存

十進制轉二進制
1  1
2  10
3  11
4  100
5  101
6  110
7  111
8  1000

64
64 / 2 = 32 -> 0
32 / 2 = 16 -> 0
16 / 2 = 8 -> 1000
// 轉爲二進制爲:100000

// 十進制 33 能夠當作是 32 + 1 ,而且 33 應該是六位二進制的(由於 33 近似 32,而 32 是 2 的五次方,因此是六位),那麼 十進制 33 就是 100001 ,只要是 2 的次方,那麼就是 1不然都爲 0
二進制轉十進制

二進制100001同理,首位是2^5(1) ,末位是2^0(0),相加得出33(只要是 2 的次方,那麼就是 1不然都爲 0)it

按位非(~) 取反

  1. 1(原碼)轉二進制: 00000001
  2. 按位取反: 11111110
  3. 將符號位以外的其它數字取反[符號位(即最高位)爲1(表示負數)]: 10000001
  4. 末位加1取其補碼: 10000010
  5. 轉換會十進制: -2
00000001 // 原碼
11111110 // 按位取反
10000001 // 除符號位取反
10000010 // +1

對任一數值 x 進行按位非操做的結果爲 -(x + 1), 例如:2 -> -3class

JS中的做用是配合indexOf()
indexOf找到一個給定元素的第一個索引,若是不存在,則返回-1, -1取反操做等於0,其它取反操做不等於0

if (~arr.indexOf(v))    if (arr.includes(v))
if (~str.indexOf(v))    if (str.indexOf(v) !== -1)

按位或(|)

規則:其中一位爲 1,結果就是 1

8 | 7
00001000
00000111
----------
00001111 // 15

任一數值 x 與 0 進行按位或操做,其結果都是 x:

6 | 0
00000110
00000000
---------
00000110 // 6

任一數值 x 與 -1 進行按位或操做,其結果都爲 -1:

6 | -1
00000110
10000001
---------
10000111

將任一數值 x 與 0 進行按位或操做,其結果都是 x。將任一數值 x 與 -1 進行按位或操做,其結果都爲 -1

JS中向下取整Math.floor, 返回小於或等於一個給定數字的最大整數

num | 0    or       Math.floor(num)
Math.floor(45.95);  // 45.95 | 0
// 45
Math.floor(45.05);  // 45.05 | 0
// 45 
Math.floor(4);  // 4 | 0
// 4 
Math.floor(-45.05);  // -45.05 | 0
// -46 
Math.floor(-45.95);  // -45.95 | 0
// -46

1 | 0 ;                       // 1

1.1 | 0 ;                     // 1

'asfdasfda' | 0 ;             // 0

0 | 0 ;                       // 0

(-1) | 0 ;                    // -1

(-1.5646) | 0 ;               // -1

[] | 0 ;                      // 0

({}) | 0 ;                    // 0

"123456" | 0 ;            // 123456

1.23E2 | 0;               // 123

1.23E12 | 0;              // 1639353344

-1.23E2 | 0;              // -123

-1.23E12 | 0;             // -1639353344

按位與(&)

規則:每一位都爲 1,結果才爲 1

8 & 7 // 0
00001000
00000111
00000000 // 0

將任一數值 x 與 0 執行按位與操做,其結果都爲 0。將任一數值 x 與 -1 執行按位與操做,其結果都爲 x。

JS中應用:
判斷奇偶性

10 & 1 // 0 偶數
11 & 1 // 1 奇數

按位異或 (^)

規則:每一位都不一樣,結果才爲 1

8 ^ 7 // 15
1000
0111
1111 // 15

8 ^ 8 // 0
1000
1000
0000 // 0

將任一數值 x 與 0 進行異或操做,其結果爲 x。將任一數值 x 與 -1 進行異或操做,其結果爲-x

不進位加法:
根據按位異或的特性就是不進位加法8 ^ 8 = 0 若是進位了,就是 16 了,因此只須要將兩個數進行異或操做,而後進位。那麼也就是說兩個二進制都是1的位置,左邊應該有一個進位1

JS中應用:
交換二個數值

let a = 3
let b = 4
a ^= b
b ^= a
a ^= b

有符號右移 (>>)

將第一個操做數向右移動指定的位數,向右被移出的位被丟棄,正數則在高位補零,負數則補1

9 >> 2

00001001 // 移動二位, 以0填充
00000010 // 2

-9 >> 2
10001001 // 原碼
11110111 // 補碼
11111101 // 補碼右移
10000011 // 原碼 // -3

公式:int v = a / (2 ^ b)

JS中的應用:
任何小數 把它>> 0能夠取整

9.99 >> 0 // 9
9 >> 0 // 9
9.19 >> 0 // 9

除法運算:

9 >> 1 // 4
8 >> 1 // 4

二分算法中取中間值:

13 >> 1 // 6
12 >> 1 // 6

topic

兩個數不使用四則運算得出和
a + b = (a ^ b) + ((a & b) << 1)
相關文章
相關標籤/搜索