js中位運(yùn)算的運(yùn)用實(shí)例分析
我們可能很少在編程中用位運(yùn)算,如果沒深入學(xué)習(xí),可能也很難理解。平時(shí)的數(shù)值運(yùn)算,其實(shí)是要先轉(zhuǎn)換成二進(jìn)制再進(jìn)行運(yùn)算的,而位運(yùn)算就是直接進(jìn)行二進(jìn)制運(yùn)算,所以位運(yùn)算的執(zhí)行效率肯定是更高的。下面通過(guò)一些實(shí)例來(lái)加深對(duì)位運(yùn)算的理解。
按位與(&)
&&運(yùn)算符我們都知道,只有兩個(gè)都為真,結(jié)果才為真。&道理是一樣的,只有兩個(gè)數(shù)的值為1時(shí),才返回1。例如1和3的按位與操作:
0001
& 0011
---------
0001
只有對(duì)應(yīng)的數(shù)為1時(shí),結(jié)果才為1,其他都為0。
判斷一個(gè)數(shù)是奇數(shù)還是偶數(shù),我們會(huì)用求余數(shù)來(lái)判斷:
function assert(n) {
if (n % 2 === 1) {
console.log("n是奇數(shù)");
} else {
console.log("n是偶數(shù)");
}
}
assert(3); // "n是奇數(shù)"
我們也可以用一個(gè)數(shù)和1進(jìn)行按位&操作來(lái)判斷,而且速度更快:
function assert(n) {
if (n & 1) {
console.log("n是奇數(shù)");
} else {
console.log("n是偶數(shù)");
}
}
assert(3); // "n是奇數(shù)"
下面是位運(yùn)算過(guò)程:
1 = 0001
3 = 0011
--------
& = 0001
奇數(shù)的二進(jìn)制碼的最后一位數(shù)肯定是1,而1只有最后一位為1,按位&操作之后,結(jié)果肯定只有最后一位數(shù)為1。而偶數(shù)的二進(jìn)制表示的最后一位數(shù)是0,和1進(jìn)行按位&操作,結(jié)果所有位數(shù)都為0。
按位或(|)
|與||操作符的道理也是一樣的,只要兩個(gè)數(shù)中有一個(gè)數(shù)為1,結(jié)果就為1,其他則為0。
0001
| 0011
---------
0011
對(duì)浮點(diǎn)數(shù)向下求整,我們會(huì)用下面的方法:
var num = Math.floor(1.1); // 1
我們也可以用位運(yùn)算來(lái)求整:
var num = 1.1 | 0; // 1
其實(shí)浮點(diǎn)數(shù)是不支持位運(yùn)算的,所以會(huì)先把1.1轉(zhuǎn)成整數(shù)1再進(jìn)行位運(yùn)算,就好像是對(duì)浮點(diǎn)數(shù)向下求整。所以1|0的結(jié)果就是1。
按位非(~)
按位非就是求二進(jìn)制的反碼:
var num = 1; // 二進(jìn)制 00000000000000000000000000000001
var num1 = ~num; // 二進(jìn)制 11111111111111111111111111111110
我們知道,js中的數(shù)字默認(rèn)是有符號(hào)的。有符號(hào)的32位二進(jìn)制的最高位也就是第一位數(shù)字代表著正負(fù),1代表負(fù)數(shù),0代表整數(shù)。那到底11111111111111111111111111111110等于多少呢?最高位為1代表負(fù)數(shù),負(fù)數(shù)的二進(jìn)制轉(zhuǎn)化為十進(jìn)制:符號(hào)位不變,其他位取反加1。取反之后為10000000000000000000000000000001,加1之后為10000000000000000000000000000010,十進(jìn)制為-2。
按位異或(^)
按位異或是兩個(gè)數(shù)中只有一個(gè)1時(shí)返回1,其他情況返回0。
0001
^ 0011
---------
0010
數(shù)字與數(shù)字本身按位異或操作得到的是0,因?yàn)槊績(jī)蓚€(gè)對(duì)應(yīng)的數(shù)字都相同,所以最后返回的都是0。
我們經(jīng)常會(huì)需要調(diào)換兩個(gè)數(shù)字的值:
var num1 = 1, num2 = 2, temp; temp = num1; num1 = num2; // 2 num2 = temp; // 1
如果裝逼一點(diǎn)的話,可以這樣:
var num1 = 1, num2 = 2; num1 = [num2, num2 = num1][0]; console.log(num1); // 2 console.log(num2); // 1
如果想再裝的穩(wěn)一點(diǎn)的話,可以這樣:
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
有符號(hào)左移(<<)
有符號(hào)左移會(huì)將32位二進(jìn)制數(shù)的所有位向左移動(dòng)指定位數(shù)。如:
var num = 2; // 二進(jìn)制10
num = num << 5; // 二進(jìn)制1000000,十進(jìn)制64
如果要求2的n次方,可以這樣:
function power(n) {
return 1 << n;
}
power(5); // 32
1的二進(jìn)制是01,左移5位就是0100000,十進(jìn)制就是2的5次方32。
有符號(hào)右移(>>)
有符號(hào)右移會(huì)將32位二進(jìn)制數(shù)的所有位向右移動(dòng)指定位數(shù)。如:
var num = 64; // 二進(jìn)制1000000
num = num >> 5; // 二進(jìn)制10,十進(jìn)制2
求一個(gè)數(shù)的二分之一:
var num = 64 >> 1; // 32
有符號(hào)左移與右移不會(huì)影響符號(hào)位。
無(wú)符號(hào)右移(>>>)
正數(shù)的無(wú)符號(hào)右移與有符號(hào)右移結(jié)果是一樣的。負(fù)數(shù)的無(wú)符號(hào)右移會(huì)把符號(hào)位也一起移動(dòng),而且無(wú)符號(hào)右移會(huì)把負(fù)數(shù)的二進(jìn)制碼當(dāng)成正數(shù)的二進(jìn)制碼:
var num = -64; // 11111111111111111111111111000000
num = num >>> 5; // 134217726
所以,我們可以利用無(wú)符號(hào)右移來(lái)判斷一個(gè)數(shù)的正負(fù):
function isPos(n) {
return (n === (n >>> 0)) ? true : false;
}
isPos(-1); // false
isPos(1); // true
-1>>>0雖然沒有向右移動(dòng)位數(shù),但-1的二進(jìn)制碼已經(jīng)變成了正數(shù)的二進(jìn)制碼:
11111111111111111111111111111111
所以-1>>>0的值為4294967295。
總結(jié)
以上的例子在平??赡軙?huì)比較容易用到或看到,也是屬于比較容易理解的。一些比較復(fù)雜的、難理解的,我覺得應(yīng)該盡量少用,因?yàn)闀?huì)給閱讀者帶來(lái)困難,也會(huì)給自己帶來(lái)麻煩。
相關(guān)文章
純js實(shí)現(xiàn)無(wú)縫滾動(dòng)功能代碼實(shí)例
這篇文章主要介紹了純js實(shí)現(xiàn)無(wú)縫滾動(dòng)功能代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-02-02
JavaScript實(shí)現(xiàn)Java中StringBuffer的方法
這篇文章主要介紹了JavaScript實(shí)現(xiàn)Java中StringBuffer的方法,實(shí)例分析了StringBuffer類的實(shí)現(xiàn)與使用技巧,需要的朋友可以參考下2015-02-02
使用Nginx部署前端項(xiàng)目的詳細(xì)步驟記錄
在實(shí)際開發(fā)中我們通常會(huì)使用Nginx來(lái)部署前端靜態(tài)頁(yè)面,以提供快速訪問速度和良好的用戶體驗(yàn),這篇文章主要給大家介紹了關(guān)于使用Nginx部署前端項(xiàng)目的詳細(xì)步驟,需要的朋友可以參考下2024-08-08
用于deeplink的js方法(判斷手機(jī)是否安裝app)
這篇文章主要介紹了用于deeplink的js方法(判斷手機(jī)是否安裝app),需要的朋友可以參考下2014-04-04
微信小程序登錄方法之授權(quán)登陸及獲取微信用戶手機(jī)號(hào)
最近改了一個(gè)公司項(xiàng)目,新增加了一個(gè)獲取用戶手機(jī)號(hào)功能,里面用到了關(guān)于獲取用戶信息和用戶手機(jī)號(hào)的功能,下面這篇文章主要給大家介紹了關(guān)于微信小程序登錄方法之授權(quán)登陸及獲取微信用戶手機(jī)號(hào)的相關(guān)資料,需要的朋友可以參考下2022-07-07

