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

位操作,其实就是直接在内存中对二进制位进行操作,由于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)--------0101011001011000    (x)
&   01010111    (x-1)--------0101000010000000    (x = -128)
&   01111111    (x-1 = 127 (with overflow))--------0000000011111111    (x = all bits 1)
&   11111110    (x-1)--------1111111000000000    (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)--------0000010001110000  (x)
&   10010000  (-x)--------0001000000000001  (x)
&   11111111  (-x)--------0000000110000000  (x = -128)
&   10000000  (-x = -128)--------1000000011111111  (x = all bits one)
&   00000001  (-x)--------0000000100000000  (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)--------1011111101110111  (x)
|   01110110  (x-1)--------0111011100000001  (x)
|   00000000  (x-1)--------0000000110000000  (x = -128)
|   01111111  (x-1 = 127)--------1111111111111111  (x = -1)
|   11111110  (x-1 = -2)--------1111111100000000  (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)--------0000000101110111  (x)--------10001000  (~x)
&   01111000  (x+1)--------0000100000000001  (x)--------11111110  (~x)
&   00000010  (x+1)--------0000001010000000  (x = -128)--------01111111  (~x)
&   10000001  (x+1)--------0000000111111111  (x = no rightmost 0-bit)--------00000000  (~x)
&   00000000  (x+1)--------0000000000000000  (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)--------1011110101110111  (x)
|   01111000  (x+1)--------0111111100000001  (x)
|   00000010  (x+1)--------0000001110000000  (x = -128)
|   10000001  (x+1)--------1000000111111111  (x = no rightmost 0-bit)
|   00000000  (x+1)--------1111111100000000  (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. java 0x3f_Java源码位操作技巧欣赏

    最近有人问些逻辑位移,算术位移的区别和应用场景,翻了一些旧材料,重新整理一下发出来,给大家欣赏一下java源码中涉及的位操作技巧,摘取的是Integer的源码实现. 整数二进制左边1最早出现的位置 p ...

  2. 位操作技巧:Bit Twiddling Hacks

    Bit Twiddling Hacks 这是CMU推荐学生去读的一份位操作的讲义: https://graphics.stanford.edu/~seander/bithacks.html

  3. 常用位操作技巧(Golang)

    2019独角兽企业重金招聘Python工程师标准>>> 1,判断奇偶 for i := 0; i < 100; i++ { if i % 2 == 0 {println(i) ...

  4. 自动挡车辆起步停车,档位操作技巧,实录详解

    多数新手朋友在驾校学的是手动挡车辆,拿本以后大多数却是购置了自动挡车辆,这样对于自动挡车辆的档位使用和操控就不太熟悉,网上虽然也有自动挡车辆档位使用的操作方法但是各家有各家的说法,这就让新手朋友们为难 ...

  5. c语言 t自己设置跳跃位置,[总结] C语言的位操作技巧

    置位 #define BIT3 (0x1 << 3) static int a; void set_bit3(void) { a |= BIT3; } void clear_bit3(vo ...

  6. 【转】位操作基础篇之位操作全面总结

    Title:       位操作基础篇之位操作全面总结 Author:     MoreWindows E-mail:      morewindows@126.com KeyWord:   C/C+ ...

  7. 位操作基础篇之位操作全面总结

    Title:       位操作基础篇之位操作全面总结 Author:     MoreWindows E-mail:      morewindows@126.com KeyWord:   C/C+ ...

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

    C 语言资源大全中文版 我想很多程序员应该记得 GitHub 上有一个 Awesome:XXX 系列的资源整理.[awesome-c](https://notabug.org/koz.ross/awe ...

  9. 这几本高分算法书助你稳步提升

    题图 | by pikisuperstar- www.freepik.com 西北望乡何处是,东南见月几回圆.又是一年中秋节,各位伙伴们是否都安好. 我猜肯定有人在家葛优躺,想好好休息一番:亦有人想趁 ...

最新文章

  1. xtrabackup周全备+增备Python脚本
  2. zabbix利用SNMPTrap接收交换机主动告警
  3. ulead gif animator_搞笑GIF趣图:这风看来很大啊,今天回不来家了7
  4. MySQL的错误:No query specified
  5. input 标签在做动画时的bug
  6. Interlocked..::.Add 方法
  7. 【转】ubuntu 12.04 LTS将关闭最大化最小化移动到右上角
  8. 山西评计算机高级职称,山西专业技术职称评审不再统一组织外语和计算机能力考试...
  9. python生成字典脚本
  10. 基于matlab和Simulink的不同阶QAM调制解调系统误码率对比仿真
  11. win10计算机记录,Win10新版计算器用法介绍
  12. 5G到底厉害在什么地方?和4G有什么不同?
  13. Unity3d 周分享(16期 2019.5.1 )
  14. 新增收货地址管理 html,关于“收货地址”的二三事
  15. 谈谈写程序与学英语 --宋劲杉
  16. 【Unity人物动画】SALSA With RandomEyes (语音生成嘴型/人物说话) 使用
  17. VMware虚拟机 扩展Ubuntu系统磁盘空间方法
  18. 【证明】矩阵的特征值即其相似对角矩阵主对角线的元素
  19. iOS - 手动下架的应用后快速恢复上架
  20. android鼠标滚轮事件坐标,android 处理鼠标滚轮事件

热门文章

  1. java 查找链表中间元素,如何找到链表的中间节点?
  2. 图层样式混合选项_ps教程,混合颜色带原理讲解
  3. 5g鸿蒙概念,华为5G概念机,真全面屏+鸿蒙系统,颜值再登巅峰
  4. oracle自定义长度异常,Oracle 自定义wmsys.wm_concat 避免长度限制
  5. 为什么不建议学python贴吧_为什么那么多自学Python的后来都放弃了,分析起来就这些原因...
  6. c语言贪心算法合并箭,贪心算法:用最少数量的箭引爆气球
  7. 返回值由hresult变为void型_java高级之泛型
  8. 系统学习深度学习(十八)--NIN模型
  9. 6. 吴恩达机器学习课程-作业6-SVM
  10. 嵌入式系统——软件测试工程