位操作实用技巧大全
2012-01-03 16:02
330 查看
检测一个无符号数是不是2^n-1(^为幂):
将最右侧0位改为1位:
获得最右侧的0
将最右侧的1位改为0位
使用位运算的无分支代码:
计算绝对值
符号函数:sign(x) = -1, x<0; 0, x == 0 ; 1, x > 0
三值比较:cmp(x,y) = -1, x<y; 0, x==y; 1, x > y
doz=x-y, x>=y; 0, x<y
不使用第三方交换x,y:
双值交换:
if (x==a) x = b;
else x = a;
//常规编码为x = ( x==a ? b :a) ;
位计数,统计1位的数量:
1.
2.
奇偶性计算:
位反转:
递增位反转后的数:
混选位:
abcd efgh ijkl mnop ABCD EFGH IJKL MNOP->aAbB cCdD eEfF gGhH iIjJ kKlL mMnN oOpP
位压缩:
选择并右移字x中对应于掩码m的1位的位,如:compress(abcdefgh,01010101)=0000bdfh
compress_left(x,m)操作与此类似,但结果位在左边: bdfh0000.
位置换:
用32个5位数表示从最低位开始的位的目标位置,结果是一个32*5的位矩阵,
将该矩阵沿次对角线转置后用5个32位字p[5]存放。
SAG(x,m) = compress_left(x,m) | compress(x,~m) ;
二进制码到GRAY码的转换:
unsigned B2G(unsigned B )
{
return B ^ (B>>1) ;
}
GRAY码到二进制码:
找出最左0字节的位置:
x&(x+1)
将最右侧0位改为1位:
x | (x+1)
获得最右侧的0
(x | (x+1))^x
将最右侧的1位改为0位
x & (x-1)
//二进制补码运算公式: -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 abs( int x ) { int y ; y = x >> 31 ; return (x^y)-y ;//or: (x+y)^y }
符号函数:sign(x) = -1, x<0; 0, x == 0 ; 1, x > 0
int sign(int x) { return (x>>31) | (unsigned(-x))>>31 ;//x=-2^31时失败(^为幂) }
三值比较:cmp(x,y) = -1, x<y; 0, x==y; 1, x > y
int cmp( int x, int y ) { return ((x>y)-(x-y)) ; }
doz=x-y, x>=y; 0, x<y
int doz(int x, int y ) { int d ; d = x-y ; return (d & ((~(d^((x^y)&(d^x))))>>31)) ; }
int max(int x, int y ) { int m ; m = (x-y)>>31 ; return (y & m | x & ~m) ; }
不使用第三方交换x,y:
x ^= y ; y ^= x ; x ^= y ; x = x+y ; y = x-y ; x = x-y ; x = x-y ; y = y+x ; x = y-x ; x = y-x ; x = y-x ; x = x+y ;
双值交换:
if (x==a) x = b;
else x = a;
//常规编码为x = ( x==a ? b :a) ;
x = a+b-x ; x = a^b^x ;
//下舍入到2的k次方的倍数: x & ((-1)<<k) (((unsigned)x)>>k)<<k //上舍入: t = (1<<k)-1 ; x = (x+t)&~t ; t = (-1)<<k ; x = (x-t-1)&t ;
位计数,统计1位的数量:
1.
int pop(unsigned x) { x = x-((x>>1)&0x55555555) ; x = (x&0x33333333) + ((x>>2) & 0x33333333 ) ; x = (x+(x>>4)) & 0x0f0f0f0f ; x = x + (x>>8) ; x = x + (x>>16) ; return (x & 0x0000003f) ; }
2.
int pop(unsigned x) { static char table[256] = { 0,1,1,2, 1,2,2,3, ...., 6,7,7,8 } ; return (table[x&0xff]+table[(x>>8)&0xff]+table[(x>>16)&0xff]+table[(x>>24)]); }
奇偶性计算:
x = x ^ ( x>>1 ) ; x = x ^ ( x>>2 ) ; x = x ^ ( x>>4 ) ; x = x ^ ( x>>8 ) ; x = x ^ ( x>>16 ) ;结果中位于x最低位,对无符号x,结果的第i位是原数第i位到最左侧位的奇偶性
位反转:
unsigned rev(unsigned x) { x = (x & 0x55555555) << 1 | (x>>1) & 0x55555555 ; x = (x & 0x33333333) << 2 | (x>>2) & 0x33333333 ; x = (x & 0x0f0f0f0f) << 4 | (x>>4) & 0x0f0f0f0f ; x = (x<<24) | ((x&0xff00)<<8) | ((x>>8) & 0xff00) | (x>>24) ; return x ; }
递增位反转后的数:
unsigned inc_r(unsigned x) { unsigned m = 0x80000000 ; x ^= m ; if( (int)x >= 0 ) do { m >>= 1 ; x ^= m ; } while( x < m ) ; return x ; }
混选位:
abcd efgh ijkl mnop ABCD EFGH IJKL MNOP->aAbB cCdD eEfF gGhH iIjJ kKlL mMnN oOpP
unsigned ps(unsigned x) { unsigned t ; t = (x ^ (x>>8)) & 0x0000ff00; x = x ^ t ^ (t<<8) ; t = (x ^ (x>>4)) & 0x00f000f0; x = x ^ t ^ (t<<4) ; t = (x ^ (x>>2)) & 0x0c0c0c0c; x = x ^ t ^ (t<<2) ; t = (x ^ (x>>1)) & 0x22222222; x = x ^ t ^ (t<<1) ; return x ; }
位压缩:
选择并右移字x中对应于掩码m的1位的位,如:compress(abcdefgh,01010101)=0000bdfh
compress_left(x,m)操作与此类似,但结果位在左边: bdfh0000.
unsigned compress(unsigned x, unsigned m) { unsigned mk, mp, mv, t ; int i ; x &= m ; mk = ~m << 1 ; for( i = 0 ; i < 5 ; ++i ) { mp = mk ^ ( mk << 1) ; mp ^= ( mp << 2 ) ; mp ^= ( mp << 4 ) ; mp ^= ( mp << 8 ) ; mp ^= ( mp << 16 ) ; mv = mp & m ; m = m ^ mv | (mv >> (1<<i) ) ; t = x & mv ; x = x ^ t | ( t >> ( 1<<i) ) ; mk = mk & ~mp ; } return x ; }
位置换:
用32个5位数表示从最低位开始的位的目标位置,结果是一个32*5的位矩阵,
将该矩阵沿次对角线转置后用5个32位字p[5]存放。
SAG(x,m) = compress_left(x,m) | compress(x,~m) ;
//准备工作: void init( unsigned *p ) { p[1] = SAG( p[1], p[0] ) ; p[2] = SAG( SAG( p[2], p[0]), p[1] ) ; p[3] = SAG( SAG( SAG( p[3], p[0] ), p[1]), p[2] ) ; p[4] = SAG( SAG( SAG( SAG( p[4], p[0] ), p[1]) ,p[2]), p[3] ) ; } //实际置换: int rep( unsigned x ) { x = SAG(x,p[0]); x = SAG(x,p[1]); x = SAG(x,p[2]); x = SAG(x,p[3]); x = SAG(x,p[4]); return x ; }
二进制码到GRAY码的转换:
unsigned B2G(unsigned B )
{
return B ^ (B>>1) ;
}
GRAY码到二进制码:
unsigned G2B(unsigned G) { unsigned B ; B = G ^ (G>>1) ; B = G ^ (G>>2) ; B = G ^ (G>>4) ; B = G ^ (G>>8) ; B = G ^ (G>>16) ; return B ; }
找出最左0字节的位置:
int zbytel( unsigned x ) { static cahr table[16] = { 4,3,2,2, 1,1,1,1, 0,0,0,0, 0,0,0,0 } ; unsigned y ; y = (x&0x7f7f7f7f) + 0x7f7f7f7f ; y = ~(y|x|0x7f7f7f7f) ; return table[y*0x00204081 >> 28] ;//乘法可用移位和加完成 }
相关文章推荐
- Python中字典创建、遍历、添加等实用操作技巧合集
- 黑莓8100 操作快捷键大全和操作技巧
- Windows Phone 实用开发技巧(2):使用TombstoneHelper简化墓碑操作 推荐
- SQL Server 数据库操作实用技巧锦集
- A1200实用技巧大全
- eclipse 操作的小实用技巧
- 数据库实用技巧操作(什么导入呀、导出呀都有了)
- JS框架的jQuery技巧实用大全
- Python字典创建 遍历 添加等实用基础操作技巧
- JavaScript中Array的一些实用操作技巧
- C#编程实用技巧:轻松实现对文件的操作
- VIM实用基本操作技巧
- SQL Server 数据库操作实用技巧锦集
- Sql Server实用操作-SQL语句导入导出大全
- Sublime Text 2 编辑器实用技巧大全
- Python中字典创建、遍历、添加等实用操作技巧合集
- Sql Server实用操作小技巧集合(转载)
- 破解常用电脑密码实用技巧大全
- Spine 实用技巧大全
- vim实用操作技巧