编程基础(三)——位运算
计算机底层是运行在二进制基础上的,高级语言所有强大的功能最后都会在计算机底层转为二进制执行。因此,基于二进制数据在运行位运算的时候远比其它数学运算、布尔操作等快得多。
什么是“位”
我们知道个位十位百位,位运算就是针对这个”数位”进行运算,对于计算机来说,位就是二进制的数位,运算符不是加减乘除,而是:按位与(AND,&)、按位或(OR,|)、按位异或(XOR,^)、按位取反(NOT,~)、移位运算 (<<, >>, >>>)。
按位与(AND,&)
当两个操作数对应位数都是 1 时,则在该位返回 1,否则则在该位返回 0;
1 | 1 & 4 // 0, 1 & 100 -> 000 |
什么意思呢?就是我们先把要进行运算的两个数转成二进制的,比如1 & 4,转成这样:
1 | 1 =》 1 |
那好我们看一共有三位,这三位我们在十进制中叫”个位””十位””百位”,但是在二进制中不应该这么叫,那我们暂时就叫”第 0 位””第 1 位””第 2 位”,那我们假想有三个开关,当两个操作数对应位数都是 1 时,则在该位返回 1,即打开结果对应位置的开关,否则关上开关。我们看”第 0 位”:一个 1 一个 0,应该是关上开关,那结果的最后一位是 0,再接着”第 1 位”和”第 2 位”也都应该关上开关,那最后得到的结果就是000。总结起来就是对应位置上的开关都开着那结果相对应的位置开关就打开,只要对应位置上有一个开关没打开,那结果相对应的位置开关就关闭。
好了,这个运算知道了,但是大家可能要问了,这样算有啥意义呢?想不到能用在哪啊?别急,我们先把其他的几个运算符讲完。
按位或(OR,|)
当两个操作数对应位数中至少有一个是 1 时,则在该位返回 1,否则则在该位返回 0;
1 | 1 | 4 // 5, 1 | 100 -> 101 |
通俗的讲就是对应位置只要有一个开关打开着那就把结果的对应位置开关打开。
按位异或(XOR,^)
当两个操作数对应位数中两个数中,一个为 1,一个为 0,则在该位返回 1,否则则在该位返回 0;
1 | 1 ^ 4 // 5, 1 ^ 100 -> 101 |
通俗的讲就是对应位置两个开关状态不一样那就把结果的对应位置开关打开,否则就关上。
按位取反(NOT,~)
在操作数对应位置,是 1 则在该位返回 0,否则则在该位返回 1;
1 | ~1 // -2, |
因为补码存在的原因,这里可能和期望的有所不同,我们可以看看这篇文章传送门:编程基础(二)——原码,反码,补码
大家会注意到这个运算符是个一元运算符,就是它跟一个操作数进行运算,我们常见的 js 一元运算符有:++、–等。这个运算符通俗来讲,就是要进行运算的这个数每个位置上正在开着的开关关上,正在关着的开关打开就得到了结果。1转成二进制就是1,按理说~1应该结果是0,但是01也是1,001也是 1,它前面的0数量不同得出的结果是不同的,这个问题我们在讲补码的时候在详细讲,现在大家先理解运算符的概念。
移位运算 (<<, >>, >>>)
移位运算的成员有点多啊!
左移运算符(<<)
按二进制形式把所有的数字向左移动对应的位数,高位移出(舍弃),低位的空位补零。
低位的空位补零好理解,什么叫高位移出舍弃?
是这样子的,如果我就有一个开关,开启状态代表数字1,那么我左移一位也就是1<<1,会有什么问题呢?问题就是我就一个开关,左移一位放不下,那就不放了,低位补 0,这就是高位移出。右移运算符(>>)
按二进制形式把所有的数字向右移动对应位移位数,低位移出(舍弃),高位的空位补符号位,即正数补零,负数补 1。