位运算
2014-03-09 14:42 夜与周公 阅读(306) 评论(0) 编辑 收藏 举报有关位运算(与运算,或运算,异或运算,左移和右移)是C/C++语言偏向底层的操作。市面上有很多有关位运算的算法技巧,特在此做了整理。
1.Bitmap
什么事Bitmap? Bitmap的核心思想就是“索引”技术,某个比特位作为key,而该比特上的值作为value(可以理解为状态位:0 or 1)。Bitmap既然利用了索引的思想,那么Bitmap这种数据结果的核心就是如何取到某个索引(即定位到某个bit)。
实现手段上肯定是利用位运算,如果想索引到第 i 比特,可以用如下代码:
(p + i /8) | (0x1 << (i%8)
其中8表示一个字节的比特位数,而p + i /8,表示Bitmap所在的字节,(p + i /8) | (0x1 << (i%8) 便可以索引到当前 i bit位置。使用上面的公式,Bitmap上的两个基本操作:索引和取值:
inline void SetBit(char* p, int pos) { p += pos / BitSize; *p = *p | (0x1 << (pos % BitSize)); } inline int Getbit(char* p, int pos) { return (*(p + pos / BitSize)) | ((pos % BitSize)) ; }
2.计算a与b的平均值
如何利用位运算实现求a与b的平均值呢?先看算法:
aveg(a, b) = (a & b) + ((a^b) >> 1)
a & b,则取出了a与b中相同的位,a与b相同位的平均值自然是自身。a^b取出了不同的位。而不同位的平均值则需要除以2,向左移动1位即可。
3.不使用加减法,求a与b的和
不使用加法而实现加法?能够想到解决的方法只能是位的运算了。考察a^b:表示了没用进位的加法,而(a&b)<<1:表示加法的进位。 a^b 与 (a&b)<<1求和,则会得到想要的结果(额,求和?递归迭代完成),代码如下:
int sum(int a, int b) { int sum = 0; int carry = 0; do { sum = a ^ b; carry = (a & b) << 1; a = sum; b = carry; } while (carry); return sum; }