是时候总结一波逻辑运算符和位运算符了。。。。。。
其实是更想总结一下位运算符的使用小技巧来体现其实用之处
&& 与:A && B,只要有一个条件为false,则结果为false
|| 或:A || B,只要有一个条件为true,则结果为true
! 非:!A,若A为false,则结果为true。若A为true ,则结果为false
&: 二进制按位与,有0即0
例如:2 & 3 = 0010 & 0011 = 0010 = 2
|: 二进制按位或,有1即1
例如:2 | 3 = 0010 | 0011 = 0011 = 3
~: 二进制按位取反【是对补码取反】
假设只有4位,实质int是32位的,但是原理是一致的
例如:2 = 0010,则~2 = 1101(注意这是补码,则原码是1011,符号位是1,表示负数)即-3
但是如果取反得到得结果符号位是0,即正数,值就是这个数
例如:-4 = 1100【原】= 1011【反】= 1100【补】
~(-4) = 0011 = 3
<<:二进制左移,相当于乘以2^n
例如:1<<4 = 16
>>:二进制右移,相当于除以2^n
例如:16>>4 = 1
^: 异或,二进制无进位相加
例如:1^0 = 1 0^0 = 0 1^1 = 0 0^1 = 1
用实例验证,正确
test.c
#include
using namespace std;
int main()
{
int a = 2&3;
int b = 2|3;
int c = ~2;
int d = 1<<4;
int e = 16>>4;
cout<<"2&3 = "<< a <>4 = "<< e <
OK,概念总结完毕(更全面的可以看此链接:C语言所有的运算符)
开始总结位运算符的实用技巧
code:
void change(int &a, int &b)
{
if(a == b) return ; //地址一样,直接退出
a = a^b;
b = a^b;
a = a^b;
}
集合{0,1,...,n-1}
的元素共n个,我们知道子集的个数是2^n个(不要忽略空集Φ)。现在需要将所有的子集枚举出来,我们可以递归实现,也可以利用&运算符的方法来求取。Code
#include
using namespace std;
#define MAXN 105
void GetSubset_1(int n, int a[], int current)
{
printf("{");
for(int i = 0; i < current; ++i)
printf("%d ",a[i]);
printf("}");
puts("");
int pos = current ? a[current-1]+1 : 0;
for (int i = pos; i < n; ++i)
{
a[current] = i;
GetSubset_1(n,a,current+1);
}
}
void GetSubset_2(int n)
{
for(int i = 0; i < (1<
(2)利用位与 & 运算,判断一个整数是否是2的整数次幂。由于二进制的权重是2,则一个数如果是2的整数次幂,则二进制表示的时候必然是最高位为1,其余都是0
keys:当一个数x是2的这个数次幂的时候,x&(x-1) = 0
因为减去1以后恰好降一位,后面的都会置为1,而前面全是0,按位&结果就是0
例子:x = 8 = (1000)2
x-1 = 7 = (0111)2
则1000 & 0111 = 0
Code:
bool fun(int num)
{
return ( (num>0) && ((num & (num-1)) == 0) );
}
(3)利用&运算符求取给定数的二进制含有1的个数,利用了(2)的思路
/**
思想:将给定数的二进制从右到左消除1,直至为0,中间统计1的个数即可
*/
int Count_Of_Num_One(int num)
{
int count = 0;
while(num)
{
num = num&(num-1);
count++;
}
return count;
}