js位運(yùn)算在實(shí)際中使用的實(shí)例教程
什么是位運(yùn)算?
從現(xiàn)代計(jì)算機(jī)中所有的數(shù)據(jù)二進(jìn)制的形式存儲(chǔ)在設(shè)備中。即 0、1 兩種狀態(tài),計(jì)算機(jī)對(duì)二進(jìn)制數(shù)據(jù)進(jìn)行的運(yùn)算(+、-、*、/)都是叫位運(yùn)算,即將符號(hào)位共同參與運(yùn)算的運(yùn)算。
按位運(yùn)算符有6個(gè)
&: 按位與\
|: 按位或\
^: 按位異或\
~: 按位取反\
>> : 右移\
<<: 左移
業(yè)務(wù)場(chǎng)景:
我們大部分的業(yè)務(wù)開發(fā)場(chǎng)景下 只用if else 或 switch 條件處理就可以,但是當(dāng)有如下場(chǎng)景:
一個(gè)ci/cd 任務(wù)有: 1.等待中 -> 2.base image1 build完成 -> 3.base image2 build 完成 -> 4. base image3 build完成 -> 5.完成/失敗
當(dāng)我們查詢狀態(tài)時(shí):有可能出現(xiàn)這樣的情況:任務(wù)處于 base image2 build 完成 但是我們查詢base image1 build 完成時(shí)該任務(wù)也應(yīng)被查詢出來(lái)。
任務(wù)處于完成狀態(tài),等我們查詢 base image3 build完成 時(shí)該任務(wù)也應(yīng)被查詢出來(lái)
是不是我們?cè)跀?shù)據(jù)庫(kù)中存儲(chǔ)的狀態(tài)枚舉值就比較麻煩?
解決辦法
辦法一:
那么這時(shí)位運(yùn)算就比較合適,定義如下枚舉:
{
waiting: 0b000001,
image1Finish: 0b000010,
image2Finish 0b000100,
image3Finish 0b001000,
finish: 0b010000,
fail: 0b100000,
}那么 上面的 [第 1 種] 情況就可以表示為:0b000001| 0b000010 | 0b000100 (waiting|image1Finish | image2Finish) 按位或
等我們判斷是否是處于 image2Finish 的時(shí)候 就可以 status & image2Finish === image2Finish 這樣判斷 。
status = 0b000001| 0b000010 | 0b000100 = 0b000111 status & image2Finish = 0b000111 & 0b000100 = 0b000100(image2Finish)
這樣是不是很好判斷? 同時(shí)提高了自己的代碼逼格?減少很多 if else 的書寫
辦法二:
其實(shí)還有另外一種做法就是 質(zhì)數(shù) 表示法:
{
waiting: 3,
image1Finish: 5,
image2Finish 7,
image3Finish 11,
finish: 13,
fail: 17,
}同樣是上面的第一個(gè)情況:
status = 3 * 5 * 7 // 判斷狀態(tài): 取模運(yùn)算 isImage2Finish = status % 7(image2Finish) === 0
附:位運(yùn)算的綜合應(yīng)用
這里有個(gè)例子——不使用加減乘除來(lái)做加法,經(jīng)常用來(lái)考察對(duì)位運(yùn)算的掌握情況。讀者可以先自行嘗試分析和實(shí)現(xiàn)。
不能用加減乘除,意思就是要你用位運(yùn)算進(jìn)行計(jì)算。以實(shí)際例子說(shuō)明,如a = 81 = 0b1010001,b = 53 = 0b0110101。通過(guò)異或運(yùn)算,我們發(fā)現(xiàn)異或把兩個(gè)數(shù)相加但是不能進(jìn)位,而通過(guò)與運(yùn)算能夠知道哪些位需要進(jìn)位,如下所示:
1010001 ^ 0110101 --------- 1100100 1010001 & 0110101 --------- 0010001
把通過(guò)與運(yùn)算得到的值向左移一位,再和通過(guò)異或得到的值相加,就相當(dāng)于實(shí)現(xiàn)了進(jìn)位,這個(gè)應(yīng)該不難理解。為了實(shí)現(xiàn)這兩個(gè)數(shù)的相加可以再重復(fù)這個(gè)過(guò)程:先異或,再與,然后進(jìn)位,直到不需要再進(jìn)位了就加完了。所以不難寫出以下代碼:
function addByBit(a, b) {
if (b === 0) {
return a;
}
// 不用進(jìn)位的相加
let c = a ^ b;
// 記錄需要進(jìn)位的
let d = a & b;
d = d << 1;
// 繼續(xù)相加,直到d進(jìn)位為0
return addByBit(c, d);
}
let ans = addByBit(5, 8);
console.log(ans);位運(yùn)算還經(jīng)常用于生成隨機(jī)數(shù)、哈希,例如Chrome對(duì)字符串進(jìn)行哈希的算法是這樣的:
uint32_t StringHasher::AddCharacterCore(uint32_t running_hash, uint16_t c) {
running_hash += c;
running_hash += (running_hash << 10);
running_hash ^= (running_hash >> 6);
return running_hash;
}不斷對(duì)當(dāng)前字符串的ASCII值進(jìn)行累加運(yùn)算,里面用到了異或,左移和右移。
總結(jié)
綜上: 當(dāng)我們的業(yè)務(wù)開發(fā)中遇到狀態(tài)數(shù) >=5 并且有交叉重疊的時(shí)候就需要考慮以上兩種辦法了。
到此這篇關(guān)于js位運(yùn)算在實(shí)際中使用的文章就介紹到這了,更多相關(guān)js位運(yùn)算使用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
js 能實(shí)現(xiàn)監(jiān)聽(tīng)F5頁(yè)面刷新子iframe 而父頁(yè)面不刷新的方法
下面小編就為大家?guī)?lái)一篇js 能實(shí)現(xiàn)監(jiān)聽(tīng)F5頁(yè)面刷新子iframe 而父頁(yè)面不刷新的方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-11-11
使用coffeescript編寫node.js項(xiàng)目的方法匯總
Node.js 基于JavaScript編寫應(yīng)用,JavaScript是我的主要開發(fā)語(yǔ)言。CoffeeScript是編譯為JavaScript的編程語(yǔ)言。CoffeeScript是一個(gè)非常高階的語(yǔ)言,將JavaScript、Ruby和Python中我最愛(ài)的部分結(jié)合在了一起。小編給大家介紹下使用coffeescript編寫node.js項(xiàng)目的方法2015-08-08
layui動(dòng)態(tài)加載多表頭的實(shí)例
今天小編就為大家分享一篇layui動(dòng)態(tài)加載多表頭的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-09-09
JavaScript中的console.profile()函數(shù)詳細(xì)介紹
這篇文章主要介紹了JavaScript中的console.profile()函數(shù)詳細(xì)介紹,本文講解了console.profile()函數(shù)的瀏覽器支持情況、console.profile()的使用、Firebug中Profile按鈕的使用等內(nèi)容,需要的朋友可以參考下2014-12-12
JS實(shí)現(xiàn)iframe中子父頁(yè)面跨域通訊的方法分析
這篇文章主要介紹了JS實(shí)現(xiàn)iframe中子父頁(yè)面跨域通訊的方法,結(jié)合實(shí)例形式分析了JS實(shí)現(xiàn)iframe頁(yè)面跨域通訊常見(jiàn)操作技巧與相關(guān)注意事項(xiàng),需要的朋友可以參考下2020-03-03
訪問(wèn)百度和谷歌網(wǎng)速測(cè)試的javascript代碼
訪問(wèn)百度和谷歌網(wǎng)速測(cè)試的javascript代碼...2007-08-08

