位运算有很大的妙用,在C语言中发扬光大。有什么作用呢?在数据结构和算法中有个很重要的概念就是:时间和空间。位运算就可以提高时间的效率和空间的利用率。
一、位运算增加空间的利用率。
没有什么神奇之处,只是以紧凑的二进制格式来描述数据结构,应用之多举不胜举。记住,最小的存储单元是bit而不是byte
二、位运算提高时间的效率。
根本原因是读取内存次数少,我们知道CPU一次读取内存的最大字节数和字长有关,正是因为把数据压缩在有限的数据结构中,读取内存的次数大大减少。
应用举例:
1、如何不使用中间变量,交换两个变量?
a = a ^ b;
b = a ^ b;
a = a ^ b;
可能会有人说使用加减法也可以,如:
a = a + b;
b = a - b;
a = a - b;
但是加减法是有副作用的,容易导致数据溢出。
2、状态的改变,我们可能经常写类似下面的代码:
if (b) {
b = false;
} else {
b = true;
}
或者更精简一点
b = b ? false : true;
但依然会别扭,因为你要改变一个标志的状态,首先要知道原有状态,使用位运算可以避免
b ^= b;
3、位向量,很多底层库中都有位向量的类,可用于很多场合,高效环保。我自己写了一个位向量,求解1亿一下素数,时间不到3秒,内存占用不到13M,可见位运算的威力。
#define LONG_BIT_LENGTH sizeof(long)
#define BIT_SHIFT_UNIT (LONG_BIT_LENGTH/8 + 1)
#define BIT_MASK (LONG_BIT_LENGTH-1)
//位向量结构:方便同时使用多个位向量
typedef struct tag_bit_vector {
long *bit_buffer; //数据区
long max_bit_num; //总bit数
}TBitVector;
//========================================================================================
//分配一个位向量
TBitVector *mallc_bit_vector(long bit_max) {
TBitVector *pbit_vector = 0;
pbit_vector = (TBitVector *)malloc(sizeof(TBitVector));
if (pbit_vector == NULL) return NULL;
pbit_vector->bit_buffer = (long *)calloc(LONG_BIT_LENGTH, (bit_max + BIT_MASK) >> BIT_SHIFT_UNIT);
if (pbit_vector->bit_buffer == NULL) return NULL;
pbit_vector->max_bit_num = bit_max;
return pbit_vector;
}
//释放一个位向量
void free_bit_vector(TBitVector *bit_vector) {
free(bit_vector->bit_buffer);
free(bit_vector);
}
//========================================================================================
//设置
void set_bit_vector(TBitVector *bit_vector, long idx) {
if (idx >= bit_vector->max_bit_num) return;
bit_vector->bit_buffer[idx >> BIT_SHIFT_UNIT] |= 1 << (idx & BIT_MASK);
}
//清除
void cls_bit_vector(TBitVector *bit_vector, long idx) {
if (idx >= bit_vector->max_bit_num) return;
bit_vector->bit_buffer[idx >> BIT_SHIFT_UNIT] &= ~(1 << (idx & BIT_MASK));
}
//探测
int test_bit(TBitVector *bit_vector, long idx) {
if (idx >= bit_vector->max_bit_num) return 0;
return bit_vector->bit_buffer[idx >> BIT_SHIFT_UNIT] & (1 << (idx & BIT_MASK));
}
求解素数代码:
int sievePrime(TBitVector *pBitVerctor, unsigned long prime)
{
unsigned long i;
if (prime*prime >= pBitVerctor->max_bit_num)
{
return 0;
}
for (i=prime<<1; i<pBitVerctor->max_bit_num; i+=prime)
{
set_bit_vector(pBitVerctor, i);
}
return -1;
}
//测试
#define PRIME_NUMBER_MAX 100000000
int main(int argc, char *argv[])
{
int milisection = 0;
int i = 0;
int primeCount = 0;
struct timeval start;
struct timeval end;
TBitVector *pdata = mallc_bit_vector(PRIME_NUMBER_MAX);
milisection = GetTickCount(&start);
for (i=2; i<PRIME_NUMBER_MAX; i++)
{
if (test_bit(pdata, i))
continue;
if (sievePrime(pdata, i) == 0)
{
break;
}
}
GetTickCount(&end);
printf("times : %d\n", (end.tv_sec * 1000 * 1000 + end.tv_usec) - (start.tv_sec * 1000 * 1000 + start.tv_usec));
free_bit_vector(pdata);
getchar();
return 0;
}
总结: 位运算应用场景还有很多,要想用好,主要看你的抽象能力。现在是大内存和多核时代,没有必要时也不建议使用,除非用在密集运算或需要高效率的算法上。
转载于:https://blog.51cto.com/8478141/1372725