位运算
位运算是把数字用二进制表示之后,对每一位上0或者1的运算。
位运算总共只有五种运算:与、或、异或、左移和右移,运算规律总结如下:
与(&): 0&0 = 0; 1&0 = 0; 0&1 = 0; 1&1 = 1.
或(|): 0|0 = 0; 1|0 = 1; 0|1 = 1; 1|1 = 1.
异或(^): 0^0 = 0; 1^0 = 1; 0^1 = 1; 1^1 = 0.
左移运算符m << n表示把m左移n位。左移的时候,最左边的n为将被丢弃,同时在最右边补上n个0。比如:00001010<<2 = 00101000,00001010<<3 = 01010000。
右移运算符m << n表示把m右移n位。左移的时候,最左边的n为将被丢弃。但右移时有两种情况:第一,数字是一个无符号数值,则用0填补最左边的n位;第二,
数字是一个有符号数值,则用符号数位填充最左边的n位,即若数字原先是正数,则右移之后在最左边补n个0,若数字原先是负数,则右移之后在最左边补n个1。
比如:00001010>>2 = 00000010 10001010>>3 = 11110001
题目:实现一个函数,输入一个整数,输出该数二进制表示中1的个数。例如把9表示成二进制是1001,有2位1。因此输入9,该函数输出2。
常规解法:
把n和1做与运算,判断n的最低位是不是为1。接着把1左移一位得到2,再和n做与运算,就能判断n的次低位是不是1……这样反复左移,每次都能判断
n的其中一位是不是。
#include<iostream>
using namespace std;
int Numberof1(int n)
{
int count = 0;
unsigned int flag = 1;
while(flag)
{
if(n & flag)
count++;
flag = flag << 1;
}
return count;
}
int main()
{
int a;
cout<<"a = ";
cin>>a;
Numberof1(a);
cout<<a<<" 的二进制中有 "<<Numberof1(a)<<" 个1."<<endl;
}
输出:
a = 9
9 的二进制中有 2 个1.
Press any key to continue
给面试官带来惊喜的解法:
把一个整数减去1,都是把该整数最右边的1变成0,如果它的后面还有0 的话,把它后面的所有0都变成1,而把它左边所有位都保持不变。接下来把这个整数和
它减去1的结果做与运算,相当于把它最右边的1变成0。例如:12(1100)减去1位11(1011)。在把1100和1011做与运算,结果得到1000.在把1000减1,得0111,把1000与0111做与运算的0000即此时为0,进行了两次与运算count为2,说明12(1100)中有两个1。
int Numberof2(int n)
{
int count = 0;
while(n)
{
++count;
n = (n-1)&n;
}
return count;
}
int main()
{
int a;
cout<<"a = ";
cin>>a;
// Numberof1(a);
Numberof2(2)
// cout<<a<<" 的二进制中有 "<<Numberof1(a)<<" 个1."<<endl;
cout<<a<<" 的二进制中有 "<<Numberof2(a)<<" 个1."<<endl;
}
相关题目:
1.用一条语句判断一个整数是不是2的整数次方。一个整数如果是2的整数次方,那么它的二进制表示中有且只有一位是1,而其他所有位都是0.(把这个整数减去
1之后再和它自己做与运算,这个整数中唯一的1就会变成0。即只能做一次与运算count = 1)
int Numberof(int n)
{
int count = 0;
while(n)
{
++count;
n=(n-1)&n;
}
if(count =1)
return true;
}
int main()
{
int n;
cout<<"整数n是否为2的整数次方"<<"n = ";
cin>>n;
Numberof(n);
cout<<"count = "<<Numberof(n)<<" 整数n是2的整数次方。"<<endl;
}
2.输入两个整数m, n计算需要改变m的二进制表示中的多少位才能达到n。比如:10的二进制1010,13的二进制1101,需要改变1010中的3位才能得到1101,。
(分为两步:第一,求这两个数的异或;第二,统计异或结果中1的位数,1的位数即为需要改变的位数。)
int Numberof3(int m, int n)
{
int count = 0;
int a = m^n;
while(a)
{
++count;
a = (a-1)&a;
}
return count;
}
int main()
{
int b,c;
cin>>b>>c;
Numberof(b,c);
cout<<Numberof(b,c)<<endl;
}
3.实现对一个8bit数据(unsigned char类型)的指定位(例如第n位)置0或者置1操作,并保持其他地位不变。
函数原型:void set_bit(unsigned char *p_data, unsigned char position, bool flag)
函数参数说明:
P_data是指定的源数据,position 是指定位(其值范围1~8);flag表示是置0还是1操作,true:置1,flase:置0.
#include<stdio.h>
void bit_set(unsigned char *p_data,unsigned char position,int flag)
{
unsigned char a=1;
a=a<<(position-1);
if(flag==1)
{
*p_data=*p_data|a;
}
if(flag==0)
{
a=~a;
*p_data=*p_data&a;
}
}
int main()
{
unsigned char c = 10 ;
bit_set(&c, 3, 1);
printf("%d\n",c);
return 0;
}