位运算总结

1.只能对整型数操作,例如char , short , int , and long(无论是有符号还是无符号)

 

2.>> , <<优先级是小于算术运算符的,因此a = b + (c >> 1)表达式中的括号不能少。特别要注意的是右移>>运算符,对于无符号数而言,左边用0填补,而对于有符号数它可能用0填补,也可能用“符号位”填补,因此当我们总是希望用0填补时,必须用unsigned声明(左移<< 总是用0填补,无论是有符号数还是无符号数)

 

3.《The C Programming language》中有几个例子还是比较经典的:

/*获取从位置P开始的n bits*/
unsigned
int getbits(unsigned x , int p , int n)
{
return (x >> (p + 1 - n)) & (~(~0 << n));
}

/*把从位置p开始的n bits反置,其余位保持不变*/
unsigned
int invert(unsigned x , int p , int n)
{
return (x ^ (~(~0 << n) << (p + 1 - n)));
}
11011001
^ 00111100(看懂这个就行了)

 

4.在《编程之美》中的中国象棋将帅问题解法1的位运算操作也是相当简洁漂亮的,在此做以记录

#define HALF_BITS_LENGTH 4
#define FULLMASK 255

#define LMASK (FULLMASK << HALF_BITS_LENGTH) //11110000
#define RMASK (FULLMASK >> HALF_BITS_LENGTH) //00001111

#define RSET(b,n) (b = ((b & LMASK) | n)) //重置右边为n
#define LSET(b,n) (b = ((b & RMASK) | (n << HALF_BITS_LENGTH))) //重置左边为n

#define RGET(b) (b & RMASK) //获取右边值
#define LGET(b) ((b & LMASK) >> HALF_BITS_LENGTH) //获取左边值

很容易把以上稍加修改来适宜任意位。

 

5.下面内容转载自:http://blog.sina.com.cn/s/blog_66ad7bba0100hf9k.html

问题:要去掉一个二进制数最低位上第一个出现的1,比如6->4, 14->12, 5->4,怎么办?
解答:最快的算法:n
&(n-1)

问题,要得到一个二进制数最低位上第一个出现的1,比如6
->2, 7->1, 12->4,怎么办?
解答:同理可得:n
-(n&(n-1))

问题:判断一个数是不是2的幂
解答:(n
&(n-1))==0 && n>0

问题:编写sign函数,参数为int n,返回值当n为负数返回
-1,正数返回1,0返回0
解答1:
return !!n - (((unsigned)n>>31)<<1)
解答2:
return !!n + (n>>31)*2 (这个不一定所有编译器上都正确)

问题:求两个整数的平均值,要考虑溢出的问题
解答:这个计算办法可以保证不会受到溢出问题的影响:(x
&y)+((x^y)>>1)

问题:求一个比n大的,并且是最小的2的幂,比如3
->4, 6->8, 100->128, 256->512
解答:
int calc(int n)
{
n
|= n>>1;
n
|= n>>2;
n
|= n>>4;
n
|= n>>8;
n
|= n>>16;
return n+1;
}

 

 

posted on 2010-05-13 20:27  DiaoCow  阅读(303)  评论(0编辑  收藏  举报

导航