大话位运算

最近遇到一个跟位运算相关的代码,想想开发这么多年来,还是上学那会在课堂上使用过,在实际的项目中从未使用过,就造成了前辈代码看不懂的困境,今天就来切身学习分享一下

看到不少网友说,大公司面试可能会经常出一些跟位运算相关的面试题,比如:

腾讯有一个:

如何检测整数 n 是否是 2 的幂次和?

在看一道Google面试题:

有64瓶药,其中63瓶是无毒的,一瓶是有毒的。如果做实验的小白鼠喝了有毒的药,3天后会死掉,当然喝了其它的药,包括同时喝几种就没事。现在只剩下3天时间,请问最少需要多少只小白鼠才能试出那瓶药有毒?

 指的是比特位(bit),不是byte,所以位运算指的就是比特位计算。

CPU所有计算都是二进制的计算,一个高性能的服务一定是把CPU资源利用到极致,也就是用最少资源换取最大收益。

在计算机世界里,万物皆0、1,0、1生万物。万物到0、1的过程叫做编码。

一个数在计算机中的二进制表示形式, 叫做这个数的机器数。机器数是带符号的,在计算机中用一个数的最高位存放符号, 正数为0, 负数为1。

计算机中对数字的编码表示有三种方式:原码反码补码

原码:原码表示法在数值前面增加了一位符号位(即最高位为符号位):正数该位为0,负数该位为1。比如十进制3如果用8个二进制位来表示就是 00000011, -3就是 10000011。

反码:反码表示方法:正数的反码是其本身;负数的反码是在其原码的基础上,符号位不变,其余各个位取反。

补码:补码表示方法:正数的补码是其本身;负数的补码是在其原码的基础上,符号位不变,其余各位取反,最后+1。 (即在反码的基础上+1)

这三种是编码方式,但是在计算机系统中,数值一律用补码来表示(存储)。

举个例子来说明下这三种码

1. 15
  原码           反码         补码
00001111  --> 00001111 --> 00001111
2. -15
10001111  --> 11110000 --> 11110001 

各种编程语言都提供了对补码的二进制位直接进行运算的方法,即位运算

符号描述规则
& 相同位的两个数字都为1,则为1;若有一个不为1,则为0。
| 相同位只要一个为1即为1。
~ 0和1全部取反。
^ 亦或 相同位不同则为1,相同则为0。
<< 左移 a << b就表示把a转为二进制后左移b位(在后面添b个0)。
>> 右移 a >> b表示二进制右移b位(去掉末b位),相当于a除以2的b次方(取整)。

 接下来举几个例子来说明下:

“&”运算

 

“|”运算

 

 

 “>>”运算

 

“<<”运算

 

 

 位运算优势

  • 存储更友好,比特位存储,不用转换后在存储
  • CPU更友好,直接比特位操作,减少机器数到比特位的转换
  • 寻址次数更少,左移一位就乘2

 

那么我来解析下前辈的代码(也就与开篇提到的腾讯面试题一个原理了):

 

 

 

 

 

posted @ 2020-09-23 10:17  砖治不服  阅读(185)  评论(0)    收藏  举报