咱们可能不多在编程中用位运算,若是没深刻学习,可能也很难理解。平时的数值运算,实际上是要先转换成二进制再进行运算的,而位运算就是直接进行二进制运算,因此位运算的执行效率确定是更高的。下面经过一些实例来加深对位运算的理解。javascript
&&运算符咱们都知道,只有两个都为真,结果才为真。&道理是同样的,只有两个数的值为1时,才返回1。例如1和3的按位与操做:java
0001 & 0011 --------- 0001
只有对应的数为1时,结果才为1,其余都为0。
判断一个数是奇数仍是偶数,咱们会用求余数来判断:编程
function assert(n) { if (n % 2 === 1) { console.log("n是奇数"); } else { console.log("n是偶数"); } } assert(3); // "n是奇数"
咱们也能够用一个数和1进行按位&操做来判断,并且速度更快:ruby
function assert(n) { if (n & 1) { console.log("n是奇数"); } else { console.log("n是偶数"); } } assert(3); // "n是奇数"
下面是位运算过程:markdown
1 = 0001 3 = 0011 -------- & = 0001
奇数的二进制码的最后一位数确定是1,而1只有最后一位为1,按位&操做以后,结果确定只有最后一位数为1。而偶数的二进制表示的最后一位数是0,和1进行按位&操做,结果全部位数都为0。学习
|与||操做符的道理也是同样的,只要两个数中有一个数为1,结果就为1,其余则为0。ui
0001 | 0011 --------- 0011
对浮点数向下求整,咱们会用下面的方法:lua
var num = Math.floor(1.1); // 1
咱们也能够用位运算来求整:spa
var num = 1.1 | 0; // 1
其实浮点数是不支持位运算的,因此会先把1.1转成整数1再进行位运算,就好像是对浮点数向下求整。因此1|0的结果就是1。code
按位非就是求二进制的反码:
var num = 1; // 二进制 00000000000000000000000000000001 var num1 = ~num; // 二进制 11111111111111111111111111111110
咱们知道,js中的数字默认是有符号的。有符号的32位二进制的最高位也就是第一位数字表明着正负,1表明负数,0表明整数。那到底11111111111111111111111111111110
等于多少呢?最高位为1表明负数,负数的二进制转化为十进制:符号位不变,其余位取反加1。取反以后为10000000000000000000000000000001
,加1以后为10000000000000000000000000000010
,十进制为-2。
按位异或是两个数中只有一个1时返回1,其余状况返回0。
0001 ^ 0011 --------- 0010
数字与数字自己按位异或操做获得的是0,由于每两个对应的数字都相同,因此最后返回的都是0。
咱们常常会须要调换两个数字的值:
var num1 = 1, num2 = 2, temp; temp = num1; num1 = num2; // 2 num2 = temp; // 1
若是装逼一点的话,能够这样:
var num1 = 1, num2 = 2;
num1 = [num2, num2 = num1][0]; console.log(num1); // 2 console.log(num2); // 1
若是想再装的稳一点的话,能够这样:
var num1 = 1, num2 = 2; num1 ^= num2; // num1 = num1 ^ num2 = 1 ^ 2 = 3 num2 ^= num1; // num2 = num2 ^ (num1 ^ num2) = 2 ^ (1 ^ 2) = 1 num1 ^= num2; // num1 = num1 ^ num2 = 3 ^ 1 = 2 console.log(num1); // 2 console.log(num2); // 1
有符号左移会将32位二进制数的全部位向左移动指定位数。如:
var num = 2; // 二进制10 num = num << 5; // 二进制1000000,十进制64
若是要求2的n次方,能够这样:
function power(n) { return 1 << n; } power(5); // 32
1的二进制是01,左移5位就是0100000,十进制就是2的5次方32。
有符号右移会将32位二进制数的全部位向右移动指定位数。如:
var num = 64; // 二进制1000000 num = num >> 5; // 二进制10,十进制2
求一个数的二分之一:
var num = 64 >> 1; // 32
有符号左移与右移不会影响符号位。
正数的无符号右移与有符号右移结果是同样的。负数的无符号右移会把符号位也一块儿移动,并且无符号右移会把负数的二进制码当成正数的二进制码:
var num = -64; // 11111111111111111111111111000000 num = num >>> 5; // 134217726
因此,咱们能够利用无符号右移来判断一个数的正负:
function isPos(n) { return (n === (n >>> 0)) ? true : false; } isPos(-1); // false isPos(1); // true
-1>>>0虽然没有向右移动位数,但-1的二进制码已经变成了正数的二进制码:
11111111111111111111111111111111
因此-1>>>0的值为4294967295。
~~用来取整
~~3.5 3
~~-2.6 -2