咱們可能不多在編程中用位運算,若是沒深刻學習,可能也很難理解。平時的數值運算,實際上是要先轉換成二進制再進行運算的,而位運算就是直接進行二進制運算,因此位運算的執行效率確定是更高的。下面經過一些實例來加深對位運算的理解。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