位操作技巧还是非常有用的。以下内容摘自CSDN,留待以后编程参考用。
http://topic.csdn.net/t/20050430/10/3977737.html
/******************************************************************/
检测一个无符号数是不为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] ;//乘法可用移位和加完成
}
/******************************************************************/
分享到:
相关推荐
C++位操作技巧 C++位操作技巧是指在C++编程语言中使用位操作符来实现各种算法和技巧的集合。本文档总结了C++位操作技巧的各种应用,包括检测无符号数、位运算公式、二进制补码运算、比较运算、无分支代码、符号函数...
位操作技巧,驱动开发,嵌入式,操作系统的高手进阶学习!
因此,熟练掌握位操作技巧对于编程来说非常重要,尤其在面临性能优化和资源限制的场景中。 位操作的基础包括六种基本操作符:与(&)、或(|)、异或(^)、非(~)、左移()、右移(>>)。这些操作符对应着不同的位操作,分别...
### 单片机C语言位操作详解 #### 一、位运算符介绍 在单片机编程中,尤其是使用C语言...在实际项目开发中,合理利用位操作技巧,可以有效提升产品的性能表现。希望读者能够深入理解这些知识点,并在实践中灵活运用。
- 复习笔记中可能涵盖了位操作的基础知识,包括每个位运算符的定义、实例和应用,以及一些常见的位操作技巧。 - 推荐的书籍如《C Primer Plus》和《C语言程序设计现代方法》等经典教材,都对位操作有详细的讲解。 ...
学习和理解这些位操作技巧,不仅能够提高你的编程效率,还能使你更好地应对各种复杂的自动化控制问题。因此,深入研究“信捷 XC系列PLC应用之位操作例程.rar”中的内容,对于提升你在PLC领域的专业技能至关重要。
### MSP430位操作C语言编程知识点解析 #### 一、引言 在嵌入式系统开发领域,微控制器...以上内容介绍了MSP430位操作C语言编程的基本知识点,希望能够帮助开发者更好地理解和掌握MSP430系列微控制器的位操作技巧。
1. 利用或操作 | 和空格将英文字符转换为小写 2. 利用与操作 & 和下划线将英文字符转换为大写 3. 利用异或操作 ^ 和空格进行英文字符大小写互换 4.
了解并熟练掌握这些位操作技巧,能帮助开发者编写出更高效、更精简的代码,更好地利用有限的硬件资源。在实际应用中,位操作常用于硬件寄存器的设置和状态检测,因为这些寄存器的每一位通常对应一个特定的功能或状态...
在嵌入式系统开发中,特别是对于AVR单片机的编程,位操作是非常常见且重要的。ICCAVR编译器提供了对AVR处理器的位操作支持,这使得开发者能够...理解并熟练运用这些位操作技巧,能够使AVR单片机的程序更加高效、简洁。
Java中的位操作是一种底层的、高效的编程技巧,它允许我们直接对二进制位进行操作。位操作在处理数据、优化代码性能等方面有着广泛的应用,尤其是在处理二进制流、节省内存资源或进行高效计算时。本文将深入探讨Java...
本教程将深入探讨如何使用凌阳61单片机驱动12864液晶,并介绍基本的位操作技巧。 首先,我们需要了解12864 LCD的基本工作原理。这种显示器通常具有128列和64行的点阵,可以显示16x16或8x8的字符。它通过串行或并行...
3. 位操作技巧:在位操作中,通过特定的位运算组合可以实现一些巧妙的功能,如快速判断一个数是否是2的幂次方。 三、实验步骤与解析 LAB2实验中,可能会涉及到以下内容: 1. 位操作实践:通过编写程序,实践使用...
在C语言中,位操作技巧包括位与(&)、位或(|)、位非(~)、位异或(^)、左移()、右移(>>)等。例如,通过位与操作可以屏蔽掉某个变量的某些位,而通过位或操作则可以为变量的某些位设置值。 5. 嵌入汇编语言的编程 在...
3. **常用位操作技巧** - **判断奇偶**: 判断一个数是否为偶数,可以通过检查其最低位(最右边的位)是否为0。如果为0,则是偶数,否则是奇数。例如,`if (a & 1) == 0`可以用来判断a是否为偶数。 - **交换两数**:...
### 编程过程中常见移位操作 ...以上介绍的位操作技巧不仅能够提高程序的运行效率,还能帮助开发者更好地理解和掌握底层数据处理的原理。这些技巧在实际开发中有着广泛的应用,尤其是在性能要求较高的场景下。
3. 位操作技巧:位操作是针对计算机最小数据单位“位”的操作,它可以让代码更加简洁高效。但需要注意位操作可能带来的安全隐患,并根据实际情况谨慎使用。 在单片机C语言编程方面,文章进一步提出了几个实用的编程...
在创新工场的笔试题中,这样的问题可能旨在测试候选人的位操作技巧和逻辑思维能力。掌握比特位操作对于理解和编写高效算法至关重要,尤其是在内存有限或者计算资源紧张的嵌入式系统中。同时,这也是一种常见的面试题...
位运算在计算机科学中扮演着...在面试中,尤其是IT巨头如微软、腾讯、百度、360等的笔试面试,位运算经常作为考察点,因此理解并灵活运用位操作技巧至关重要。通过学习和实践,可以提升编程能力和解决复杂问题的能力。