--------------------------------------------------------------------------------------------------------------------------------------------------------------

位操作,其实就是直接在内存中对二进制位进行操作,由于CPU支持位操作,因此位操作的效率是很高的,但是位操作只能进行2的倍数的操作。下面介绍位运算的一些小技巧。

-------------------------------------------------------------------------------

一直以来,对位操作比较迷糊,也一直想了解,所以今天在网上查了些资料,发现一篇bithacks写的不错,因此节选翻译给大家!第一次翻译!英文有点烂!大家见谅!

此篇文章节选翻译自   http://www.catonmat.net/blog/low-level-bit-hacks-you-absolutely-must-know/


1、测试给定数字的奇偶性

if ((x & 1) == 0) {
x is even
} else {
x is odd
}

判断一个数是不是奇数,只需要判断该数的二进制表示的末尾是不是1即可。

通过举个简单的例子,给大家讲解下!

    00101011
& 00000001 (note: 1 is the same as 00000001)
--------
00000001

通过上面的例子可以看到,将给定数字与1进行 ‘与运算’如果结果为1则是奇数,否则为偶数。

2、测试给定数字的第n位是否是1

if (x & (1<<n)) {
n-th bit is set
} else {
n-th bit is not set
}

在第一个例子中,我们通过  x&1 来判断第一个二进制位是否是1.本条技巧扩展了技巧1的结果。

通过将1向左移动n位然后与判定数字进行与运算来判断该位置是否置1.

1         00000001    (same as 1<<0)
1<<1 00000010
1<<2 00000100
1<<3 00001000
1<<4 00010000
1<<5 00100000
1<<6 01000000
1<<7 10000000

eg.122的第三位置1了吗?

122 & (1<<3)

其中,122的二进制表示为:01111010  &

1<<3 的二进制表示为:00001000
                         ------------

00001000

结果不为0,因此,122的二进制表示的第三位是1.

3、将给定数字的第n位置1

y =  x | (1<<n)

这是由于 1 or 0 或者 1 or 1 结果该位都会被置1.

假设给定数字为120,我们希望把第二位打开。

其中,120的二进制表示为:  01111000   (120 的二进制表示)

|  00000100    (1<<2)

--------

01111100

这个很简单吧!

4、将给定数字的第n位置0

y =  x & ~(1<<n)

此种情况下一个重要的技巧是:~(1<<n),它把除了第n位的其他位都置1了。

看起来是下面的这个样子:

~1        11111110  (same as ~(1<<0))
~(1<<1) 11111101
~(1<<2) 11111011
~(1<<3) 11110111
~(1<<4) 11101111
~(1<<5) 11011111
~(1<<6) 10111111
~(1<<7) 01111111

而且,0& what 都等于0.因此,就关闭了第n位,而不会对其它位造成影响。

下面看一个例子,将127的第四位置0.

   01111111    (127 in binary)
& 11101111 (~(1<<4))
--------
01101111

5、将给定数字的第n位的数字转换(如是0,转成1;如是1,转成0)

看到上面的讲解大家应该知道用异或运算了。

y = x ^ (1<<n)

下面看个具体的例子:假设想要把01110101的第五位转换下。

   01110101
^ 00100000
--------
01010101

假设是这个数字的第五位呢, 01010101

   01010101
^ 00100000
--------
01110101

发现什么规律没有,异或两次会返回同样的值,异或这种精致的技巧被用来计算RAID 阵列的均衡性,但这都是在其他论文里面才有的。

6、将给定数字的最右边的1置0

y = x & (x-1)

这个技巧将最右边的1-bit 置0。举个例子,给定整数:00101010(最右边的1用黑体标识了),

经过转换后变成了00101000

下面再给几个例子:

    01010111    (x)
& 01010110 (x-1)
--------
01010110 01011000 (x)
& 01010111 (x-1)
--------
01010000 10000000 (x = -128)
& 01111111 (x-1 = 127 (with overflow))
--------
00000000 11111111 (x = all bits 1)
& 11111110 (x-1)
--------
11111110 00000000 (x = no rightmost 1-bits)
& 11111111 (x-1)
--------
00000000

为什么能达到这个效果呢?

如果你仔细思考一会,你应该能想到,会出现以下两种情况:

1)给定数字最右边有1.在这种情况下,将该数减1,会将原数中所有的0位置1,并且将最右边的1置0(想想为什么?).

然后,进行与运算,将最右边的1置0.

因此,如果你将转换后的数字加上1,那么你就得到了原来的数字。

2)给定数字最右边没有1(all 0).此种情况下,再减去1的话,会将所有的为置1,因此进行与运算的时候又得到了原来的数。


7、除了最右边的1,其他位置0

y = x & (-x)

这个位操作技巧能够找到最右边的1,并且将其他位置0。

例如,     01010100(最右边的1用黑体标识)

被转换成   00000100

看下面更多的例子:

    10111100  (x)
& 01000100 (-x)
--------
00000100 01110000 (x)
& 10010000 (-x)
--------
00010000 00000001 (x)
& 11111111 (-x)
--------
00000001 10000000 (x = -128)
& 10000000 (-x = -128)
--------
10000000 11111111 (x = all bits one)
& 00000001 (-x)
--------
00000001 00000000 (x = all bits 0, no rightmost 1-bit)
& 00000000 (-x)
--------
00000000

这个技巧能够起作用是因为:-x 和 ~x+1 是相等的
.

8、将最右边的 1的 右边位置 置0

y = x | (x-1)

这个技巧最好通过例子来讲解,比如,给定的值是01010000,将会被转换成01011111.所有的从右边到最右边1的位被置1.

这是一个不太精致的技巧,它会将0的所有位置1.

让我们来看更多的例子:

    10111100  (x)
| 10111011 (x-1)
--------
10111111 01110111 (x)
| 01110110 (x-1)
--------
01110111 00000001 (x)
| 00000000 (x-1)
--------
00000001 10000000 (x = -128)
| 01111111 (x-1 = 127)
--------
11111111 11111111 (x = -1)
| 11111110 (x-1 = -2)
--------
11111111 00000000 (x)
| 11111111 (x-1)
--------
11111111

让我们来证明一下:

也是有两种情况,

1)没有最右边的1,这种情况下x = 0,x-1 = -1,-1的二进制表示为11111111,或运算会将所有的位置1,尽管不是想要的结果,但情况确实是这样。

2)有最右边的1.让我们把这个数分成两部分,x-1会将修改右边的位,将有1的置为0,将低位置1,然后 x | (x-1),让所有1保留,让最右边的1保留,并且将最右边的1后面的位置1.(这点翻译的不太好,建议看原文:There is the rightmost 1-bit bi. Let's divide all the bits in two groups again (like in the previous example). Calculating x-1 modifies only bits to the right, turning bi into 0, and all the lower bits to 1's. Now OR-ing x with x-1 leaves all the higher bits (to the left) the same, leaves bit bi as it was 1, and since lower bits are all low 1's it also turns them on. The result is that the rightmost 1-bit got propagated to lower order bits.)

9、此技巧与技巧7正好相反,

  找到最右边的0,将它置1,所以其他位置0

   y = ~x & (x+1)

下面看一些例子:

    10111100  (x)
--------
01000011 (~x)
& 10111101 (x+1)
--------
00000001 01110111 (x)
--------
10001000 (~x)
& 01111000 (x+1)
--------
00001000 00000001 (x)
--------
11111110 (~x)
& 00000010 (x+1)
--------
00000010 10000000 (x = -128)
--------
01111111 (~x)
& 10000001 (x+1)
--------
00000001 11111111 (x = no rightmost 0-bit)
--------
00000000 (~x)
& 00000000 (x+1)
--------
00000000 00000000 (x)
--------
11111111 (~x)
& 00000001 (x+1)
--------
00000001

证明:假设有一个最右边的0,因此,~x,将最右边的0置1,然后x+1会将最右边的0置1,然后与运算后除最右边的0变成1,所有其他位被置0了。

9、将最右边的0置1

y = x | (x+1)

例如:给定数字为10100011

转换后为10100111

更多的例子:

    10111100  (x)
| 10111101 (x+1)
--------
10111101 01110111 (x)
| 01111000 (x+1)
--------
01111111 00000001 (x)
| 00000010 (x+1)
--------
00000011 10000000 (x = -128)
| 10000001 (x+1)
--------
10000001 11111111 (x = no rightmost 0-bit)
| 00000000 (x+1)
--------
11111111 00000000 (x)
| 00000001 (x+1)
--------
00000001

证明:将x和x+1进行或运算不会丢失任何信息。将x加1后,填充了最右边的第一个0。结果是max(x,x+1).如果x+1 溢出的话,那就没有0位了。如果不溢出,结果就会把最右边的第一个0置为1.

最后作者还提供了一个将一个十进制的整数转换成2进制的小程序:

void int_to_bin(int num) {
char str[9] = {0};
int i;
for (i=7; i>=0; i--) {
str[i] = (num&1)?'1':'0';
num >>= 1;
}
printf("%s\n", str);
}

-----------------------------------------------------------------------------------------------------------------

翻译完成,希望能够帮助到你!

转载请注明!链接:http://blog.csdn.net/luozhaowork/article/details/10362905

Thank any way!

BitHacks--位操作技巧的更多相关文章

  1. delphi.位操作

    位操作网上有很多介绍,请上网google/baidu,比如: 位操作技巧实例大全: http://blog.csdn.net/g_spider/article/details/5750665 位操作基 ...

  2. Java位操作全面总结

    转载: Java位操作全面总结 在计算机中所有数据都是以二进制的形式储存的.位运算其实就是直接对在内存中的二进制数据进行操作,因此处理数据的速度非常快.在实际编程中,如果能巧妙运用位操作,完全可以达到 ...

  3. Java位操作全面总结[ZZ]

    Java位操作全面总结 在计算机中所有数据都是以二进制的形式储存的.位运算其实就是直接对在内存中的二进制数据进行操作,因此处理数据的速度非常快.在实际编程中,如果能巧妙运用位操作,完全可以达到四两拨千 ...

  4. C 语言资源大全中文版

    C 语言资源大全中文版 我想很多程序员应该记得 GitHub 上有一个 Awesome - XXX 系列的资源整理.awesome-c 是 koz.ross 发起维护的 C 语言资源列表,内容包括了: ...

  5. Java数据结构和算法 - 哈希表

    Q: 如何快速地存取员工的信息? A: 假设现在要写一个程序,存取一个公司的员工记录,这个小公司大约有1000个员工,每个员工记录需要1024个字节的存储空间,因此整个数据库的大小约为1MB.一般的计 ...

  6. 嵌入式、C语言位操作的一些技巧汇总

    下面分享关于位操作的一些笔记: 一.位操作简单介绍 首先,以下是按位运算符: 在嵌入式编程中,常常需要对一些寄存器进行配置,有的情况下需要改变一个字节中的某一位或者几位,但是又不想改变其它位原有的值, ...

  7. 嵌入式开发中常见3个的C语言技巧

    Hey,大家好!我是CrazyCatJack.今天我来说几个在嵌入式开发中常用的C语言技巧吧.也许你曾经用过,也许你只是见到过但是没有深入理解.那么今天好好补充下吧^_^ 1.指向函数的指针 指针不光 ...

  8. ps技巧

    ADOBE PHOTOSHOP 同义词 PS(位图图像处理软件Photoshop)一般指ADOBE PHOTOSHOP 本词条由“科普中国”百科科学词条编写与应用工作项目 审核 . Adobe Pho ...

  9. Java 性能优化技巧集锦

    摘要: =================================== 可供程序利用的资源(内存.CPU时间.网络带宽等)是有限的,优化的目的就是让程序用尽可能少的资源完成预定的任务.优化通常 ...

随机推荐

  1. 抄书(B - 二分查找)

    抄书  (二分查找+贪心) 提示:二分查找一般写成非递归形式 时间复杂度:O(logn) 题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action? ...

  2. A. Liserious战队

    Liserious战队是一支活跃在京沪地区的著名密室逃脱战队,在优秀的队长Liserious和芳姐的带领下,打遍天下大大小小的密室逃脱,攻无不克,战无不胜,上天入地无所不能. 世界密室逃脱委员会以IS ...

  3. VS2010/MFC对话框二:为对话框添加控件)

    为对话框添加控件 创建对话框资源需要创建对话框模板.修改对话框属性.为对话框添加各种控件等步骤,前面一讲中已经讲了创建对话框模板和修改对话框属性,本节继续讲如何为对话框添加控件. 上一讲中创建了一个名 ...

  4. PHP 自学之路-----XML编程(Xpath技术,simpleXml技术)基础入门

    XPAth技术 XPath的设计的核心思想,可以通过xpath迅速简介的定位到你希望查找的节点.主要目的是描述节点相对其他节点的位置,可以取得所有符合条件的节点,成为[位置路径]. Xapth主要用来 ...

  5. iOS中的图像处理(二)——卷积运算

    关于图像处理中的卷积运算,这里有两份简明扼要的介绍:文一,文二. 其中,可能的一种卷积运算代码如下: - (UIImage*)applyConvolution:(NSArray*)kernel { C ...

  6. Jquery ajax方法详解

    1.url: 要求为string类型的参数,(默认为当前页面地址)发送请求的地址. 2.type: 要求为String类型的参数,请方式(get/post)默认为get.注意其他HTTP请求方法,例如 ...

  7. HDU OJ 5326 Work( 2015多校联合训练第3场) 并查集

    题目连接:戳ME #include <iostream> #include <cstdio> #include <cstring> using namespace ...

  8. likely() and unlikely()

    likely() and unlikely() http://www.cnblogs.com/yangzd/archive/2010/09/27/1837202.html 在linux中判断语句经常会 ...

  9. 由zImage生成uImage

    一.手动使用mkimage命令 mkimage -A arm -O linux -T kernel -C none -a 30007fc0 -e 30007fc0 -n uImage   -d /wo ...

  10. tomcat解析之简单web服务器(图)

    链接地址:http://gogole.iteye.com/blog/587163 之前有javaeyer推荐了一本书<how tomcat works>,今天晚上看了看,确实不错,第一眼就 ...