位操作技巧大全

原创 2005年05月06日 14:21:00


检测一个无符号数是不为2^n-1(^为幂): x&(x+1)

将最右侧0位改为1位: 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:
1.x ^= y ; y ^= x ; x ^= y ;
2.x = x+y ; y = x-y ; x = x-y ;
3.x = x-y ; y = y+x ; x = y-x ;
4.x = y-x ; x = y-x ; x = x+y ;

双值交换:x = a, x==b; b, x==a//常规编码为x = x==a ? b :a ;
1.x = a+b-x ;
2.x = a^b^x ;

下舍入到2的k次方的倍数:
1.x & ((-1)<<k)
2.(((unsigned)x)>>k)<<k
上舍入:
1. t = (1<<k)-1 ; x = (x+t)&~t ;
2.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] ;//乘法可用移位和加完成
}

位操作技巧实例大全

检测一个无符号数是不为2^n-1(^为幂): x&(x+1)将最右侧0位改为1位: x | (x+1)二进制补码运算公式:-x = ~x + 1 = ~(x-1)~x = -x-1 -(~x) = x...
  • sunyubo458
  • sunyubo458
  • 2009年07月24日 17:52
  • 362

wine使用小技巧

首先附上正文地址http://forum.ubuntu.org.cn/viewtopic.php?t=72933 下面是正文,鉴于Wine的迅猛发展,本文的内容已经有些已经不适用了。Wine的自...
  • u011405324
  • u011405324
  • 2014年01月22日 11:37
  • 362

职场必备, Word技巧大全

Word中常用快捷键 “字体”对话框 Ctrl+D 选择框式工具栏中的“字体”框 Ctrl+Shift+F 加粗 Ctrl+B 倾斜 Ctrl+I 下划线Ctrl+U “上标”效果 C...
  • qq_35038153
  • qq_35038153
  • 2017年04月19日 22:41
  • 188

Google顶级搜索引擎搜索方法使用技巧大全(一)

随着时间的推移,搜索已经成为生活工作的一部分。工作需要搜索技术文档、客户信息;购物需要搜索商品信息和指南;娱乐需要搜索相关背景资料和图片。不知不觉中,搜索已经变得无处不在。在后互联网时代、面对海量信息...
  • yakoo5
  • yakoo5
  • 2010年12月18日 10:22
  • 1917

位操作技巧

检测一个无符号数是不为2^n-1(^为幂):   x&(x+1)         将最右侧0位改为1位:   x   |   (x+1)         二进制补码运算公式:     -x   =  ...
  • oncreate
  • oncreate
  • 2007年05月30日 12:17
  • 1013

微信小程序:小技巧系列合辑No.1

微信小程序小技巧系列《一》幻灯片,tab导航切换:    http://www.wxapp-union.com/portal.php?mod=view&aid=70 微信小程序小技巧系列《二》sho...
  • rolan1993
  • rolan1993
  • 2017年06月06日 15:09
  • 554

必知的 15 个jQuery小技巧(干货)

1.返回顶部按钮 你可以利用 animate 和 scrollTop 来实现返回顶部的动画,而不需要使用其他插件。 $('a.top').click(function(){ $(docum...
  • jian_xi
  • jian_xi
  • 2017年05月20日 14:52
  • 348

Jquery需要掌握的技巧

检查 jQuery 是否加载在使用 jQuery 进行任何操作之前,你需要先确认它已经加载:if (typeof jQuery == 'undefined') { console.log('jQu...
  • u011225629
  • u011225629
  • 2016年03月14日 09:05
  • 2415

23个位运算技巧

20个位运算技巧 1.获得int型最大值 int getMaxInt(){ return (1
  • itismelzp
  • itismelzp
  • 2015年12月16日 13:53
  • 808

十秒钟解决 Ecilipse调试时出现 cannot connect to Vm 问题

前几天,在调试程序的时候发现不能调试啦!出现了这个提示 cannot connect to Vm ,出现这个问题可能造成某些不变,例如,我在测试UDP通信时,代码 没有问题,但总是有错误,不能进行通...
  • MFSGSS3432
  • MFSGSS3432
  • 2012年03月10日 08:27
  • 1370
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:位操作技巧大全
举报原因:
原因补充:

(最多只允许输入30个字)