NOIP普及组-位运算

按位与、按位或、按位异或、取反、左移还有右移

Posted by 周琪岳 on July 8, 2021

位运算概述

位运算:对二进制形式的每一位进行的运算

接下来是六种基本的位运算

按位与(&)

按位与的规则

按位与:两边都是1的时候结果才是1,其余都为0

第一个数 第二个数 按位与的结果
0 0 0
0 1 0
1 0 0
1 1 1

按位与的步骤

1.先将两个数转换为二进制数

2.按照二进制数的低位对齐,高位不够补0

3.逐位进行按位与操作,规则即为上述表格,算出来的结果即为二进制按位与的结果

4.转为十进制,大功告成

按位或(|)

按位或的规则

按位或:两边只要有1个是1,那么结果就是1,否则结果为0,在数学上叫做可兼或

第一个数 第二个数 按位或的结果
0 0 0
1 0 1
0 1 1
1 1 1

按位或的步骤

1.先将两个数转换为二进制数

2.按照二进制数的低位对齐,高位不够则补0

3.逐位进行按位或操作,规则即为上述表格,算出来的结果即为二进制按位或的结果;

4.转为十进制,大功告成

按位异或(^)

按位异或的规则

按位异或:如果两边相同,则结果为0,否组结果为1,数学中叫做排斥或

第一个数 第二个数 按位或的结果
0 0 0
1 0 1
0 1 1
1 1 0

按位异或的步骤

1.先将两个数转换为二进制数

2.按照二进制数的低位对齐,高位不够则补0

3.逐位进行按位异或操作,规则即为上述表格,算出来的结果即为二进制按位异或的结果;

4.转为十进制,大功告成

按位取反 (~)

按位取反的规则+步骤

按位取反:将数转为二进制,逐位将数字取反

数字 按位取反的结果
0 1
1 0

看起来非常容易~~~

左移 («)

左移的规则+步骤

左移:在数的二进制形式下,在后面补0

举例

原数 左移几位 结果
10110 1 101100
111 3 111000
10101010101 6 10101010101000000

左移的特殊用法

值得注意的是,数字左移x位,实际上相当于乘上2的x次方

右移(»)

右移的规则+步骤

右移:在数的二进制形势下,去掉最后x位即可

举例

原数 右移几位 结果
10110 1 1011
111 2 1
10101010101 3 10101010
代码小贴士:在写分治、二分、线段树等需要大量对2进行乘除操作的算法时,可以用"x << 1"与"x >> 1" 代替,因为位运算的时间复杂度比乘除低很多。还有一个要注意的是,位运算一定要打括号,因为位运算的优先级极低,本人就在小学省赛时翻过这个错误!

有趣的题目

为了统计一个非负整数的二进制形式中1的个数,代码如下:

1
2
3
4
5
6
7
8
int CountBit(int x) {
    int ret = 0;
    while(x) {
        ret ++;
        ______________;
    }
    return ret
}

则空格内需要填入的语句是:

1
2
3
4
A. x>>=1
B. x &= x - 1
C. x |= x >> 1
D. x <<=1
答案:B 。设一个二进制数代入模拟即可。(A、D代入后答案错误,C在很多情况会全1导致死循环)

位运算的运用博大精深,在近几年的比赛题目中经常出现,一定要尤为重视。希望大家能够多刷题练习,灵活使用位运算优化自己的代码,CSP-J2021rp++!!!