在研究某大佬的代码时,突然发现了这样一条用来判断奇偶数的语句:
if(x&1) {...}
带着想探究事物本质的好奇心 (代码说它想变得高大上!),去搜了搜取模运算%
和按位与&
的关系,于是打开了新世界的大门 (「・ω・)「
- 注:
位运算与&
的效率要比取模运算%
快10倍以上
位运算符简介
与&
、或|
、异或^
、右移>>
、左移<<
,取反~
按位与 &
- 0&0=0; 0&1=0; 1&0=0; 1&1=1; 简记为“同1则1”
- 应用:
- 清零:x&0
- 取二进制数的某一位:例如取x=10010110的右数第三位,则
x&00000100 = 00000100
,说明x的右数第三位是1 - 判断奇偶数代替
取模运算x%2==1
: 奇数x&1=1,偶数x&1=0,效率更高
按位或 |
- 0|0=0; 0|1=1; 1|0=1; 1|1=1; 简记为“有1则1”
- 应用:
- 使二进制数的某些位为1:例如使x=10001000的右数第1,2位取1,则
x|00000011 = 10001011
- 使二进制数的某些位为1:例如使x=10001000的右数第1,2位取1,则
按位异或 ^
- 0^0=0; 0^1=1; 1^0=1; 1^1=0; 简记为“同0异1”
- 自反性:
x^y^y = x
;x^0 = 0
;x^x = 0
- 应用:
- 不利用中间变量实现变量值互换:
//x = 3 = 0011 y = 5 = 0101 x = x^y; // x1 = (x^y=0110) y = x^y; // y = (x1^y=0110^0101=0011=3) x = x^y; // x = (x1^y1=0110^0011=0101=5) 交换完成
- 特殊的数组筛选重复值:1~100放在长度为101的数组中,只有唯一的一个值重复,其它均只出现一次 -> 将数组中的元素全部异或,再减去1-100的全部异或,即可得到重复的数值
按位右移 >>
- 将某数的二进制位全部右移指定位,相当于除以2n,正数左补0,负数左补1,右边移出去的位丢弃,例如
00100110>>2 = 00001001 即 38>>2 = 38/4 = 9(余数舍弃)
按位左移 <<
- 将某数的二进制位全部左移指定位(当移出的位中不含1时,相当于乘以2n)右补0,左边移出去的位丢弃,例如
00001101<<2 = 00110100 即 13<<2 = 13*4 =52
按位取反 ~
- 将某数的二进制位数全部取反,0变1,1变0,例如
~52 = ~00110100 = 11001011 = 203 = 255-52
综合应用示例
- 防溢出求平均数:
(x+y)/2
⇒(x&y)+((x^y)>>1)
- 求绝对值:
int abs(int x) { int y; y = x >> 31; return (x^y)-y; //(x+y)^y }
- 替代部分条件语句:
if (x==a) x = b; else x = a;
⇒x = (x==a ? b : a);
⇒x = a ^ b ^ x;