刷题的时候碰见了一些位运算,有印象但是对它们的算法实际用处不了解,于是就再次回顾一下其表现特征,归纳一下了解到的知识点~
参考:
规则:
正数:反码、原码、补码相同,符号位为0
负数:反码,符号位为1,数值位按位取反
? 补码,反码+1
已知负数补码求原码:符号位不变,数值位减1再取反; 或者,符号位不变,数值位取反后再加1
NSLog(@"1左移-->%d",1<<1);//0001 -->2
NSLog(@"2左移-->%d",2<<1);//0010 -->4
NSLog(@"3左移-->%d",3<<1);//0011 -->6
NSLog(@"4左移-->%d",4<<1);//0100 -->8
NSLog(@"5左移-->%d",5<<1);//0101 -->10
NSLog(@"6左移-->%d",6<<1);//0110 -->12
NSLog(@"7左移-->%d",7<<1);//0111 -->14
NSLog(@"8左移-->%d",8<<1);//1000 -->16
NSLog(@"1右移-->%d",1>>1);//0001 -->0
NSLog(@"2右移-->%d",2>>1);//0010 -->1
NSLog(@"3右移-->%d",3>>1);//0011 -->1
NSLog(@"4右移-->%d",4>>1);//0100 -->2
NSLog(@"5右移-->%d",5>>1);//0101 -->2
NSLog(@"6右移-->%d",6>>1);//0110 -->3
NSLog(@"7右移-->%d",7>>1);//0111 -->3
NSLog(@"8右移-->%d",8>>1);//1000 -->4
NSLog(@"按位与-->%d",0&0);//0000 & 0000 0
NSLog(@"按位与-->%d",0&1);//0000 & 0001 0
NSLog(@"按位与-->%d",1&0);//0001 & 0000 0
NSLog(@"按位与-->%d",1&1);//0001 & 0001 1
NSLog(@"按位与-->%d",2&2);//0010 & 0010 2
NSLog(@"按位与-->%d",4&4);//0100 & 0100 4
NSLog(@"按位与-->%d",-2&2);// 2
NSLog(@"按位与-->%d",-4&4);// 4
//判断奇偶性
NSLog(@"按位与-->%d",0&1);//0
NSLog(@"按位与-->%d",1&1);//1
NSLog(@"按位与-->%d",2&1);//0
NSLog(@"按位与-->%d",3&1);//1
/*
-2 和 2为例:
1000 0000 0000 0010 -2原码
1111 1111 1111 1101 -2反码
1111 1111 1111 1110 -2补码
0000 0000 0000 0010 2 结果为2
*/
NSLog(@"按位或-->%d",0|0);//0000 & 0000 0
NSLog(@"按位或-->%d",0|1);//0000 & 0001 1
NSLog(@"按位或-->%d",1|0);//0001 & 0000 1
NSLog(@"按位或-->%d",1|1);//0001 & 0001 1
NSLog(@"按位或-->%d",2|2);//0010 & 0010 2
NSLog(@"按位或-->%d",4|4);//0100 & 0100 4
NSLog(@"按位或-->%d",-2|2);// -2
NSLog(@"按位或-->%d",-4|4);// -4
/*
-2 和 2
1000 0000 0000 0010 原码
1111 1111 1111 1101 反码
1111 1111 1111 1110 补码
0000 0000 0000 0010 2补码
1111 1111 1111 1110 结果为补码,如果是负数需要转成原码
1111 1111 0000 0001 符号位不变,取反
1111 1111 0000 0010 +1 为-2
*/
NSLog(@"0按位非-->%d",~0);//0000 -1
NSLog(@"1按位非-->%d",~1);//0000 -2
NSLog(@"2按位非-->%d",~2);//0010 -3
NSLog(@"3按位非-->%d",~3);//0010 -4
NSLog(@"4按位非-->%d",~4);//0100 -5
NSLog(@"-2按位非-->%d",~-2);// 1
NSLog(@"-4按位非-->%d",~-4);// 3
/*
0000 0000 0000 0000 0
1111 1111 1111 1111 按位取反
1111 1111 0000 0001 负数,符号位不变,取反+1 结果为-1
1111 1111 0000 0010 -2
1111 1111 1111 1110 -2补码
0000 0000 0000 0001 取反,正数,结果为1
1111 1111 0000 0100 -4
1111 1111 1111 1100 -4补码(取反+1)
0000 0000 0000 0011 3
*/
NSLog(@"按位异或-->%d",0^0);//0
NSLog(@"按位异或-->%d",0^1);//1
NSLog(@"按位异或-->%d",1^2);//3
NSLog(@"按位异或-->%d",-2^1);//-1
NSLog(@"按位异或-->%d",-3^-2);//3
/*
0^1
0000 0000 0000 0000 0
0000 0000 0000 0001 1
0000 0000 0000 0001 1
1^2
0000 0000 0000 0001 1
0000 0000 0000 0010 2
0000 0000 0000 0011 3
-2^1
1111 1111 0000 0010 -2 原码
1111 1111 1111 1110 -2补码(取反+1)
0000 0000 0000 0001 1
1111 1111 1111 1111 符号位为负数,求其原码
1111 1111 0000 0001 -1(取反+1)
-3^-2
1111 1111 0000 0011 -3原码
1111 1111 1111 1101 -3补码
1111 1111 1111 1110 -2补码
0000 0000 0000 0011 3
*/
1. 整数的平均值
对于两个整数x,y,如果用 (x+y)/2 求平均值,会产生溢出,因为 x+y 可能会大于INT_MAX,但是我们知道它们的平均值是肯定不会溢出的,我们用如下算法:
int average(int x, int y) //返回X,Y 的平均值
{
return (x&y)+((x^y)>>1);
}
2. 判断一个整数是不是2的幂,对于一个数 x >= 0
boolean power2(int x)
{
return ((x&(x-1))==0)&&(x!=0);
}
3. 用位运算符交换两个整数
void swap(int x , int y)
{
x ^= y;
y ^= x;
x ^= y;
}
4. 计算绝对值
int abs( int x )
{
int y ;
y = x >> 31 ;
return (x^y)-y ; //or: (x+y)^y
}
5. 求相反数
x 的 相反数
(~x+1)
6.判断奇偶性
a&1 = 0 偶数
a&1 = 1 奇数
位运算总结 (左移、右移、按位与、按位或、按位非、按位异或)
原文:https://www.cnblogs.com/xiaoqiangink/p/14366099.html