关于二进制的运算

提出问题

刷知乎的时候遇到一个非常有意思的题目,引发了一些思考:
写一个函数,输入一个整数,判断是否是奇数,将结果返回。

1
2
3
public boolean isOdd(int number){

}

前言

上面的问题可以说简单的不能再简单了,但是对于初级开发人员或是中级开发人员,甚至是高级开发人员的面试都可以用的到,涉及的侧重点也是不同的。
开始解决问题之前先巩固一下Java位运算知识。

>>和<<

>>右移运算符

含义:将运算符左边的对象向右移动运算符右边指定的位数。使用符号扩展机制,也就是说,如果值为正,则在高位补0,如果值为负,则在高位补1。
例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
6 >> 2
先将6转为二进制
00000000 00000000 00000000 00000110
6为正数,高位补0,再右移两位得到:
00000000 00000000 00000000 00000001
所以6 >> 2得到的是1

-6 >> 2
-6为负数,转为二进制是
10000000 00000000 00000000 00000110
得反码
11111111 11111111 11111111 11111001
得补码(+1
11111111 11111111 11111111 11111010
右移两位
11111111 11111111 11111111 11111110
所以-6 >> 2得到的是-2

<<左移运算符

含义:左移运算符,将运算符左边的对象向左移动运算符右边指定的位数(在低位补0)
例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
6 << 2
6转为二进制
00000000 00000000 00000000 00000110
左移两位,低位补0
00000000 00000000 00000000 00011000
所以6 << 2得到的是24

-6 << 2
将-6转为二进制
10000000 00000000 00000000 00000110
取反码
11111111 11111111 11111111 11111001
取补码
11111111 11111111 11111111 11111010
左移两位
11111111 11111111 11111111 11101000
再取补码
10000000 00000000 00000000 00011000
所以-6 << 2得到的是24

|(或),&(与),~(非)和^(异或)

或运算符

含义:两个位只要有一个为1,那么结果就是1,否则就为0
例如:

1
2
3
13 | 2      ——>     00001101 | 00000010

00001111 ——> 15

与运算符

含义:两个操作数中位都为1,结果才为1,否则结果为0
例如:

1
2
3
13 & 2      ——>     00001101 & 00000010

00000000 ——> 0

非运算符

含义:如果位为0,结果是1,如果位为1
例如:

1
2
3
4
5
~ 2      ——>     ~ 00000000 00000000 00000000 00000010

11111111 11111111 11111111 11111101 ——>(取补码) 10000000 00000000 00000000 00000011
得到
-3

异或运算符

含义:两个操作数的位中,相同则结果为0,不同则结果为1。
例如:

1
2
3
13 ^ 2      ——>     00001101 ^ 00000010

00001111 ——> 15

解决方式

现在回头看看开场的题目:
简单明了方式:

1
2
3
4
5
6
7
public boolean isOdd(int number){
if(number % 2 == 1){
return true;
}else{
return false;
}
}

我们可以再改改:

1
2
3
public boolean isOdd(int number){
return (number % 2) == 1;
}

但是如果输入负数就不行了。
所以再改:

1
2
3
public boolean isOdd(int number){
return (number % 2) != 0;
}

我们知道位运算是比模运算效率更高的,而且奇数的二进制数最低位为1,偶数为0。前面的准备就是为最后一步做铺垫的。
所以可以改成:

1
2
3
public boolean isOdd(int number){
return (number & 1) == 1;
}