开发人员应该知道哪些有用的按位运算符代码技巧?

我必须说我从来没有理由使用按位运算符,但是我确信有一些我已经执行的操作可以更有效地完成它们。 如何“转移”和“OR-ing”帮助您更有效地解决问题?

看到着名的Bit Twiddling Hacks
大多数乘法/除法运算是不必要的 – 编译器会自动执行这些操作,只会让人们感到困惑。

但是,如果使用硬件或通信协议,则会有一堆“检查/设置/切换位N”types的黑客。

对string(字符)使用按位操作

将字母转换为小写

  • OR by space => (x | ' ')
  • 结果总是小写,即使信件已经是小写字母
  • 例如。 ('a' | ' ') => 'a' ; ('A' | ' ') => 'a'

将字母转换为大写字母

  • AND by underline => (x & '_')
  • 即使字母已经是大写,结果总是大写
  • 例如。 ('a' & '_') => 'A' ; ('A' & '_') => 'A'

反转信的情况:

  • XOR by space => (x ^ ' ')
  • 例如。 ('a' ^ ' ') => 'A' ; ('A' ^ ' ') => 'a'

字母在字母表中的位置

  • AND by chr(31) / binary('11111') /( hex('1F') => (x & "\x1F")
  • 结果在1..26的范围内,字母大小写不重要
  • 例如。 ('a' & "\x1F") => 1 ; ('B' & "\x1F") => 2

获取字母的字母位置 (仅限大写字母):

  • AND ? => (x & '?') XOR by @ => (x ^ '@')
  • 例如。 ('C' & '?') => 3 ; ('Z' ^ '@') => 26

获取字母的位置 (仅限小写字母):

  • XOR by backtick / chr(96) / binary('1100000') / hex('60') => (x ^ '`')
  • 例如。 ('d' ^ '`') => 4 ; ('x' ^ '`') => 25

注意:使用英文字母以外的任何东西都会产生垃圾结果


  • 整数上的按位运算(int)

获取最大整数

 int maxInt = ~(1 << 31); int maxInt = (1 << 31) - 1; int maxInt = (1 << -1) - 1; 

获取最小整数

 int minInt = 1 << 31; int minInt = 1 << -1; 

获得最长的时间

 long maxLong = ((long)1 << 127) - 1; 

乘以2

 n << 1; // n*2 

除以2

 n >> 1; // n/2 

乘以2的m次幂

 n << m; 

除以2的m次方

 n >> m; 

检查奇数

 (n & 1) == 1; 

交换两个值

 a ^= b; b ^= a; a ^= b; 

获得绝对的价值

 (n ^ (n >> 31)) - (n >> 31); 

获取两个值的最大值

 b & ((ab) >> 31) | a & (~(ab) >> 31); 

获取两个值的最小值

 a & ((ab) >> 31) | b & (~(ab) >> 31); 

检查两者是否有相同的标志

 (x ^ y) >= 0; 

计算2 ^ n

 2 << (n-1); 

是否是2的阶乘

 n > 0 ? (n & (n - 1)) == 0 : false; 

模2 ^ n对m

 m & (n - 1); 

得到平均水平

 (x + y) >> 1; ((x ^ y) >> 1) + (x & y); 

得到n的第m位(从低到高)

 (n >> (m-1)) & 1; 

将n的第m位设置为0(从低到高)

 n & ~(1 << (m-1)); 

n + 1

 -~n 

n – 1

 ~-n 

获取对比数字

 ~n + 1; (n ^ -1) + 1; 

if(x == a)x = b; if(x == b)x = a;

 x = a ^ b ^ x; 

我用过的频率只有三个:

  1. 设置一下:a | = 1 << bit;

  2. 清除一下:a&=〜(1 << bit);

  3. testing一下位:a&(1 << bit);

Matters Computational:Ideas,Algorithms,Source Code,by Jorg Arndt(PDF) 。 这本书包含了大量的东西,我通过http://www.hackersdelight.org/上的链接find它。;

平均没有溢出

计算两个参数x和y的平均值(x + y)/ 2的例程是

 static inline ulong average(ulong x, ulong y) // Return floor( (x+y)/2 ) // Use: x+y == ((x&y)<<1) + (x^y) // that is: sum == carries + sum_without_carries { return (x & y) + ((x ^ y) >> 1); } 

你可以压缩数据,例如整数集合:

  • 查看集合中哪些整数值更频繁地出现
  • 使用短位序列来表示更频繁出现的值 (以及更长的位序列来表示出现频率较低的值)
  • 连接比特序列:例如,结果比特stream中的前3个比特可能代表一个整数,接下来的9比特代表另一个整数等等。

计数设置位,find最低/最高设置位,find第n个从顶部/底部设置位和其他可以是有用的,这是值得看的位twiddling黑客站点。

也就是说,这种事情不是日常重要的。 有用的库,但即使如此,最常见的用途是间接的(例如使用一个bitset容器)。 另外,理想情况下,这些将是标准的库函数 – 在一些平台上,使用专门的CPU指令可以更好地处理这些函数。

1)除以2的幂

foo >>= x; (除以2的幂)

foo <<= x; (乘以2的幂)

2)交换

 x ^= y; y = x ^ y; x ^= y; 

虽然乘法/移位似乎很漂亮,但我偶尔需要的唯一一件事就是将布尔变换成位。 为此,您需要按位与/或,并可能位移/倒置。

我想要一个函数来将数字舍入到下一个最高次幂,所以我访问了几次被提出的Bit Twiddling网站,并提出了这个问题:

 i--; i |= i >> 1; i |= i >> 2; i |= i >> 4; i |= i >> 8; i |= i >> 16; i++; 

我在size_ttypes上使用它。 它可能不会在签名types上发挥作用。 如果您担心可移植到不同大小types的平台,请在适当位置使用#if SIZE_MAX >= (number)指令来洒上您的代码。

我使用按位运算符来高效地实现位串的距离计算。 在我的应用程序中,位串被用来表示位置在一个离散的空间(一个八叉树 ,如果你感兴趣,用莫顿sorting编码)。 距离计算需要知道网格上的点是否落在特定的半径内。