位运算
1. 判断一个数是奇数还是偶数?
首先大家会想到是
cout << (i % 2 ? "奇数" : "偶数") << endl;
那么有没有更简单的方法呢?当然有,例如用位运算,只用比较二进制最后一位就可以了。
cout << (i & 0x1 ? "奇数" : "偶数") << endl;
2. 判断以下三段代码哪些代码输出值相同
- 第一段:
#include <stdio.h>
int main()
{
unsigned char a = 0xA0; /*为无符号字符型变量 a 赋值为十六进制的 A0*/
unsigned char c = ~a; /*将 a 的取反结果赋给变量 c*/
unsigned char b = c >> 4; /*将变量 c 右移 4 位后的结果赋给 b*/
printf("b = %d\n", b);
return 0;
}
- 第二段:
#include <stdio.h>
int main()
{
unsigned char a = 0xA0; /*定义无符号变量a并初始化,值为十六进制的A0*/
unsigned char b = ~a >> 4; /*将 a 取反并右移 4 位的结果赋给无符号变量 b*/
printf("b = %d\n", b);
return 0;
}
- 第三段:
#include <stdio.h>
int main()
{
char a = 0xA0; /*定义变量 a 为有符号的字符型变量*/
unsigned char b = ~a >> 4; /*将 a 取反并右移 4 位的结果赋给无符号变量 b*/
printf("b = %d\n", b);
return 0;
}
第一段和第三段
如果是在 32 位系统上运行程序,位运算是按 32 位计算的,而且是按照符号位进行扩展。无符号的数,在其转换的二进制数前边补 0;有符号的数,按当前符号位来补。
- 第一段:
a 为无符号数,a = 0xA0,a = 1010 0000。a 的取反过程为
a = 0000 0000 0000 0000 0000 0000 1010 0000
~a = 1111 1111 1111 1111 1111 1111 0101 1111
因为 c 为无符号数,所以 c = 0101 1111,c >> 4 = 0000 0101,因此 b = 5。
- 第二段:
a 为无符号数,a = 0xA0,a = 1010 0000。a 的取反过程为
a = 0000 0000 0000 0000 0000 0000 1010 0000
~a = 1111 1111 1111 1111 1111 1111 0101 1111
b = ~a >> 4 = 1111 0101 = 245 。
- 第三段
a 为有符号数,a = 0xA0,a = 1010 0000。a 的取反过程为
a = 1111 1111 1111 1111 1111 1111 1010 0000
~a = 0000 0000 0000 0000 0000 0000 0101 1111
b = ~a >> 4 =0000 0101 = 5 。
3. 输入一个数,实现其低 4 位翻转
#include <iostream>
#include <bitset>
using namespace std;
int main()
{
while(1)
{
int i;
cin >> i;
cout << bitset<8>(i) << endl;
cout << (i ^ 0xF) << endl;
cout << bitset<8>(i ^ 0xF) << endl;
}
}
4. 给定 int a; 计算它有多少个 bit 是 1 ?
#include <iostream>
#include <bitset>
using namespace std;
int main()
{
while(1)
{
int i;
cin >> i;
cout << bitset<8>(i) << endl;
cout << (i ^ 0xF) << endl;
cout << bitset<8>(i ^ 0xF) << endl;
}
}
或者
#include <iostream>
using namespace std;
int main()
{
int i;
cin >> i;
int count;
for (int k = 0; k < 16; k++)
{
if (i & 1)
count++;
i >>= 1;
}
cout << count << endl;
return 0;
}