位运算:
对整数在内存中的二进制位进行操作。一般操作如下:
操作数的存放方式也分为大端模式,小端模式;大端模式:从高字节到低字节。小端模式:从低字节到高字节。
例如0x1234的存放方式:
小端:
大端:
内存地址 | 存放内容 |
0x4000 | 0x34 |
0x4001 | 0x12 |
内存地址 | 存放内容 |
0x4000 | 0x12 |
0x4001 | 0x34 |
判断存放方式是大端还是小端模式:
void checkCpu(){
unsigned short data = 0x1122;
unsigned char *p = (unsigned char *)&data;
if(*p==0x22)
小端
else
大端
}
介绍2个位运算的等式:
-n = ~(n-1)=-n+1;
获取二进制位的最后一个1:n&(-n);
去掉二进制位的最后一个1:n&(n-1);
位运算实现平均数(防止大数相加之后的溢出情况):
int anverage(int x,int y){
return (x&y)+((x^y)>>1);
}
位运算实现绝对值:
int abs(int x){
//负数右移31位 变成0xffffffff 正数则为:0x00000000
int y;
y = x>>31;
return (x^y)-y;
}
int add(int num1,int num2){
/**
二进制加法:0+0=0;0+1=1;1+0=1;1+1=0进位是1;
所以类似于异或操作,只有进位的时候选择的x&y 1&1=1,0&0=0不存在进位
*/
int tmp,carry;
if(num2 == 0)
return num1;
tmp = num1^num2;
carry = (num1&num2)<<1;
return add(tmp,carry);
}
位运算实现乘法:
int multi(int a,int b){
/**
分析 乘法同时也是加法的一种变形
1011*1010 = 1011*1000+1011*0010;
好比1011<<3 + 1011<<1;
通过上面的tips:获取1:n&(-n) 去掉1:n&(n-1)
通过map<int,int>存储数值 和位数
*/
bool flag = (b<0);
if(b<0) b = -b;
if(a==0 || b==0)
return 0;
map<int,int> bit_map;
int i;
int sum=0;
for(i=0;i<32;i++)
bit_map.insert(1<<i,i);
while(b>0){
int last_one = bit_map[b&(-b)];
sum += a<<(last_one);
b &= (b-1);
}
if(flag)
return -sum;
else
return sum;
}
位运算实现除法:
int div(const int x,const int y){
int left_num = x;
int ans = 0;
while(left_num>=y){
int mul = 1;
while(y*mul <=(left_num)>>1)
mul <<= 1;
ans += mul;
left_num -= y*mul;
}
return ans;
}