# Java中的位运算

Java中的位运算主要有以下几种

| 运算描述  | 运算符 | 运算规则                        | 例子                                                                          |          |          |          |         |
| ----- | --- | --------------------------- | --------------------------------------------------------------------------- | -------- | -------- | -------- | ------- |
| 与     | &   | 都是1，结果才为1；其他情况结果为0          | <p>1&1=1<br>1&0=0<br>0&1=0<br>0&0=0</p>                                     |          |          |          |         |
| 或     | \|  | 只要有1个1，结果就为1；都是0的时候，结果才为0；  | <p>1                                                                        | 1=1<br>1 | 0=1<br>0 | 1=1<br>0 | 0=0</p> |
| 取反    | \~  | 1变0，0变1                     | <p>\~0=1<br>\~1=0</p>                                                       |          |          |          |         |
| 异或    | ^   | 相同为0，不同为1                   | <p>1^1=0<br>0^0=01<br>1^0=1<br>0^1=1</p>                                    |          |          |          |         |
| 右移    | >>  | a >> b ：所有位右移b位，高位补0        | <p>5 >> 1 ===>  0000 0000 0000 0101 >> 1  = 0000 0000 0000 0010 = 2<br></p> |          |          |          |         |
| 左移    | <<  | a << b：所有位左移b位，低位补0         | 5 << 1 ===>  0000 0000 0000 0101 << 1  = 0000 0000 0000 1010 = 10           |          |          |          |         |
| 无符号右移 | >>> | a >>> b ：除符号位外，其他位右移b位，高位补0 |                                                                             |          |          |          |         |
| 无符号左移 | <<< | a <<< b：除符号位外，其他位左移b位，低位补0  |                                                                             |          |          |          |         |

注：位运算时，进行运算的两个数，要转换为二进制，然后从最低位到最高位，一一对应。上面所述的运算规则，均为某位上的两个值的运算规则。例子均是某个位的数值。

**要注意** ①位操作只能用于整形数据，对float和double类型进行位操作会被编译器报错。 ②位操作符的运算优先级比较低，因为尽量使用括号来确保运算顺序，否则很可能会得到莫明其妙的结果。 \*\*

## 位运算的技巧或应用

**1、乘或除2（或2的倍数4/8/16/32...）的情形，可以考虑使用左移或右移，即**`<<`**或** `>>`

```java
int a = 9;
int b = a << 1 = 18
int c = a >> 1 = 4
```

**2、判断奇偶** 这里利用一个特性：偶数的二进制最低位必为0，奇数的二进制最低位必为1。

```java
//判断i是否为偶数
boolean even = (i & 1) == 0;
//这里有一个小小的常犯的错误，如下代码判断是否为奇数是有问题的：负的奇数运算结果为-1。
boolean odd = (i & 1) == 1;
//正确的判断奇数
boolean odd = ((i & 1) == 1) || ((i & 1) == -1);
```

解释：1的二进制为0000 0000 0000 0001，对任意的偶数（无论正负），其形式为xxxx xxxx xxxx xxx0（x表示0或1），两数进行与运算，从高位起的前31位必为0，最后一位是1&0=0，所以结果必然是0000 0000 0000 0000。

**3、交换两个数的值** 利用的特性： ①任意一个数a，a^a=0，且a^0=a，则a^a^a=a ②a^b=b^a

```java
int a = 10, b = 20;
a = a^b;//a = 10^20 = 不关心
b = a^b;//b = 10^20^20 = 10
a = a^b;//a = 10^20^10^20^20 = 20
```

**4、变换符号** 变换符号其实就是正数变负数，负数变正数。 其实代码中 a = -a就可以实现，这里只是提供另一种可以使用位运算的方式：a = (\~a) + 1

```java
int a = 10, b = -20;
a = (~a) + 1 = (~10) + 1 = -10
b = (~b) + 1 = (~(-20)) + 1 = 20
```

**5、求绝对值** 思路①：取符号位，判断其正负 a >> 31：取符号位，0为正数，-1位负数(TODO why)

```
abs(a) = (a >> 31) == 0 ? a : (~a + 1)
```

思路②：利用特性：对任意整数a，a^(-1) = \~a;

```
int i = a >> 31;//a为正数，则i=0;a为负数，则i=-1;
abs(a) = (a^i) - i;
//a为正数，则(a^0) - 0 = a;
//a为负数，则(a^(-1)) + 1 =
```

TODO 运算示例以及更多应用

## 参考

[可能是最通俗易懂的 Java 位操作运算讲解](https://juejin.im/entry/58f9b6118d6d8100588060d6)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://maxwell.gitbook.io/way-to-architect/ji-suan-ji-cao-zuo-xi-tong/ji-suan-ji-ji-chu/java-zhong-de-wei-yun-suan.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
