位运算的应用
这个主题是两三周前候教授课上讲得一些内容。关于位运算,这个计算机最原始,最神秘的东西。它能做的事一定超远了你的想象能力。
说实话,下面的内容基本上没有原创的,这个我真的原创不来。罗列了一些,位运算的运用。本来想讲它们都写成函数的形式,可惜是在是太多了……
不过还是先说在前头,这些东西最大的意义在于让人了解一下计算机世界的神奇,那些超越了我们一般思考能力的东西。其次的意义在于当有人问你如何不使用条件语句如何判断两个数的大小时,你可以淡定地告诉他位运算。关于真正意义上的使用,在比较高的层面上,那些可以加快运行速度的方法比如说移位乘,编译器都会帮你优化,没必要自己写。而且使用为运算会带来非常非常严重的代码移植性问题。总之我至今是以娱乐的心情看待这个客体。
关于参考资料,网上零零散散有一些文章,还可以。这里推荐一本书《Hacker's Delight》(你能理解我为什么对这个抱娱乐的心情了吧)。CSDN上有提供下载。值得收藏,无聊的时候也许会去翻一翻。
用这么不正经的态度对待如此高尚的东西,我表示有点不安。
不在废话了直接看代码。纯C代码,没有引用,bool类型要添加stdbool.h才可以用
1: //不使用临时变量交换两个数
2: void swap(int *a, int *b)
3: {
4: *a = *a ^ *b;
5: *b = *b ^ *a;
6: *a = *a ^ *b;
7: }
8: //获取低8位
9: short getLow8(short number)
10: {
11: return (number & 0XFF);
12: }
13: //获取高8位
14: short getHeight8(short number)
15: {
16: return ((number & 0XFF00) >> 8);
17: }
18: //检查一个无符号整数是否为2的幂
19: //将一个最右侧为1的位改为0
20: bool checkPowerOf2 (unsigned short x)
21: {
22: return !(x & (x - 1));
23: }
24: //检查一个无符号整数是否为(2的n次方 - 1)
25: bool checkPowerOf2Sub1(unsigned short x)
26: {
27: return !(x & (x + 1));
28: }
29: //析出(isolate)最右侧为1的位
30: short isolate1(short x)
31: {
32: return x & (-x);
33: }
34: //析出(isolate)最右侧为0的位
35: short isolate0(short x)
36: {
37: return (~x & (x + 1));
38: }
39: //乘以32
40: short mul32(short x)
41: {
42: //32 = 2 ^ 5
43: return x << 5;
44: }
45: //乘以20
46: short mul20(short x)
47: {
48: //20=2^4+2^2
49: return (x << 4) + (x << 2);
50: }
51: //判断是否为奇数
52: bool isOdd(int x)
53: {
54: return !(x & 1);
55: }
56: //比较
57: int min(int x, int y)
58: {
59: return ((x |~y)&((x^y) |~(y-x))) ? x : y;
60: }
下面再列出一些引用。是在太多了
-x = ~x + 1 = ~(x-1)
~x = -x-1
-(~x) = x+1
~(-x) = x-1
x+y = x - ~y - 1 = (x |y)+(x&y)
x-y = x + ~y + 1 = (x |~y)-(~x&y)
x^y = (x |y)-(x&y)
x |y = (x&~y)+y
x&y = (~x |y)-~x
x==y: ~(x-y |y-x)
x!=y: x-y |y-x
x < y: (x-y)^((x^y)&((x-y)^x))
x <=y: (x |~y)&((x^y) |~(y-x))
x < y: (~x&y) |((~x |y)&(x-y))//无符号x,y比较
x <=y: (~x |y)&((x^y) |~(y-x))//无符号x,y比较
计算绝对值 int y ; y = x >> 31 ; return (x^y)-y ; //or: (x+y)^y
整数的平均值
对于两个整数x,y,如果用 (x+y)/2 求平均值,会产生溢出,
因为 x+y 可能会大于INT_MAX,但是我们知道它们的平均值是肯定不会溢出的
return (x&y)+((x^y)>>1);
取int型变量a的第k位 (k=0,1,2……sizeof(int)) a>>k&1
将int型变量a的第k位清0 a=a&~(1<
截取old变量第row位,并将该位信息装配到变量new的第15-k位 new |= ((old >> row) & 1) << (15 – k)