# 位元運算子

> 了解位元運算子(& | ^)與位移運算子(<< >> >>>)的基本使用。

## 位元運算子

我們知道資料在記憶體中都是以0/1的方式儲存，如果想直接對這些位元做運算，Java提供了一些位元運算子供設計師使用。

| Operator運算子 | 描述                    | 範例 (令a, b為數值) |
| ----------- | --------------------- | ------------- |
| \~          | 位元補數(complement)運算    | \~a           |
| &           | 位元和(and)運算            | a & b         |
| \|          | 位元或(or)運算             | a \| b        |
| ^           | 位元互斥或(exclusive or)運算 | a ^ b         |

## 補數 complement (\~)：

補數的意思就是1變0，0變1，反向的感覺。

範例程式：

```java
int a = 45;
System.out.println(a);
a = ~a;
System.out.println(a);
```

執行結果：

```java
45    // 00000000000000000000000000101101
-46   // 11111111111111111111111111010010
```

## 和 and (&)：

和運算，是二元運算，只有兩個都為1，結果才是1。

範例程式：

```java
int a = 45;
int b = 25;
System.out.println(a & b);
```

執行結果：

```java
//   a = 00000000000000000000000000101101
//   b = 00000000000000000000000000011001
9    //  00000000000000000000000000001001
```

AND真值表：

| **&** | **1** | **0** |
| ----- | ----- | ----- |
| **1** | 1     | 0     |
| **0** | 0     | 0     |

## 或 or (|)：

或運算，是二元運算，只要有一個1，結果就是1。

範例程式：

```java
int a = 45;
int b = 25;
System.out.println(a | b);
```

執行結果：

```java
//  a = 00000000000000000000000000101101
//  b = 00000000000000000000000000011001
61  //  00000000000000000000000000111101
```

OR 真值表：

| **\|** | **1** | **0** |
| ------ | ----- | ----- |
| **1**  | 1     | 1     |
| **0**  | 1     | 0     |

## 互斥或 exclusive or (^)：

互斥或，英文縮寫常稱『XOR』，是二元運算子，位元不同為1。

程式範例：

```java
int a = 45;
int b = 25;
System.out.println(a ^ b);
```

執行結果；

```java
// a = 00000000000000000000000000101101
// b = 00000000000000000000000000011001
52  // 00000000000000000000000000110100
```

XOR 真值表：

| **^** | **1** | **0** |
| ----- | ----- | ----- |
| **1** | 0     | 1     |
| **0** | 1     | 0     |

## 位移運算子 Bit Shift Operators

位移運算子的目的是向左或向右移動目標運算元的每個位元。

| Operator運算子 | 描述         | 範例 (令a, b為數值)        |   |
| ----------- | ---------- | -------------------- | - |
| <<          | 保留正負號的左移運算 | a << b (將a逐位元左移b個單位) |   |
| >>          | 保留正負號的右移運算 | a >> b (將a逐位元右移b個單位) |   |
| >>>         | 右移運算       | a >>> b              |   |

範例程式：

```java
int a = 16;
int b = 2;
System.out.println(a << b);
System.out.println(a >> b);
System.out.println(a >>> b);
```

執行結果：

```java
// a = 00000000000000000000000000010000
64  // 00000000000000000000000001000000
4   // 00000000000000000000000000000100
4   // 00000000000000000000000000000100
```

範例程式2 (負號測試)：

```java
int a = -16;
int b = 2;
System.out.println(a << b);
System.out.println(a >> b);
System.out.println(a >>> b);
```

執行結果：

```java
       //  a = 11111111111111111111111111110000
-64         // 11111111111111111111111111000000
-4          // 11111111111111111111111111111100
1073741820  // 00111111111111111111111111111100
```

(無號右移>>>，不會理會當前的符號位元，直接右移補0上去)

### ※利用位元位移運算子，可以達到最快的 \*2 或 /2 運算。

嘛，因為根本沒做到數學運算，而乘法跟除法在計算上是很廢時的。

範例程式：

```java
int a = 3;
System.out.println(a * 2 * 2 * 2 * 2 * 2);  
System.out.println(a << 5);

int b = 20000;
System.out.println(b / 2 / 2 / 2 / 2 / 2);
System.out.println(b >> 5);
```

執行結果：

```java
96
96
625
625
```
