js位運(yùn)算在實際中使用的實例教程
什么是位運(yùn)算?
從現(xiàn)代計算機(jī)中所有的數(shù)據(jù)二進(jìn)制的形式存儲在設(shè)備中。即 0、1 兩種狀態(tài),計算機(jī)對二進(jìn)制數(shù)據(jù)進(jìn)行的運(yùn)算(+、-、*、/)都是叫位運(yùn)算,即將符號位共同參與運(yùn)算的運(yùn)算。
按位運(yùn)算符有6個
&: 按位與\
|: 按位或\
^: 按位異或\
~: 按位取反\
>> : 右移\
<<: 左移
業(yè)務(wù)場景:
我們大部分的業(yè)務(wù)開發(fā)場景下 只用if else 或 switch 條件處理就可以,但是當(dāng)有如下場景:
一個ci/cd 任務(wù)有: 1.等待中 -> 2.base image1 build完成 -> 3.base image2 build 完成 -> 4. base image3 build完成 -> 5.完成/失敗
當(dāng)我們查詢狀態(tài)時:有可能出現(xiàn)這樣的情況:任務(wù)處于 base image2 build 完成 但是我們查詢base image1 build 完成時該任務(wù)也應(yīng)被查詢出來。
任務(wù)處于完成狀態(tài),等我們查詢 base image3 build完成 時該任務(wù)也應(yīng)被查詢出來
是不是我們在數(shù)據(jù)庫中存儲的狀態(tài)枚舉值就比較麻煩?
解決辦法
辦法一:
那么這時位運(yùn)算就比較合適,定義如下枚舉:
{ waiting: 0b000001, image1Finish: 0b000010, image2Finish 0b000100, image3Finish 0b001000, finish: 0b010000, fail: 0b100000, }
那么 上面的 [第 1 種] 情況就可以表示為:0b000001| 0b000010 | 0b000100 (waiting|image1Finish | image2Finish) 按位或
等我們判斷是否是處于 image2Finish 的時候 就可以 status & image2Finish === image2Finish 這樣判斷 。
status = 0b000001| 0b000010 | 0b000100 = 0b000111 status & image2Finish = 0b000111 & 0b000100 = 0b000100(image2Finish)
這樣是不是很好判斷? 同時提高了自己的代碼逼格?減少很多 if else 的書寫
辦法二:
其實還有另外一種做法就是 質(zhì)數(shù) 表示法:
{ waiting: 3, image1Finish: 5, image2Finish 7, image3Finish 11, finish: 13, fail: 17, }
同樣是上面的第一個情況:
status = 3 * 5 * 7 // 判斷狀態(tài): 取模運(yùn)算 isImage2Finish = status % 7(image2Finish) === 0
附:位運(yùn)算的綜合應(yīng)用
這里有個例子——不使用加減乘除來做加法,經(jīng)常用來考察對位運(yùn)算的掌握情況。讀者可以先自行嘗試分析和實現(xiàn)。
不能用加減乘除,意思就是要你用位運(yùn)算進(jìn)行計算。以實際例子說明,如a = 81 = 0b1010001,b = 53 = 0b0110101。通過異或運(yùn)算,我們發(fā)現(xiàn)異或把兩個數(shù)相加但是不能進(jìn)位,而通過與運(yùn)算能夠知道哪些位需要進(jìn)位,如下所示:
1010001 ^ 0110101 --------- 1100100 1010001 & 0110101 --------- 0010001
把通過與運(yùn)算得到的值向左移一位,再和通過異或得到的值相加,就相當(dāng)于實現(xiàn)了進(jìn)位,這個應(yīng)該不難理解。為了實現(xiàn)這兩個數(shù)的相加可以再重復(fù)這個過程:先異或,再與,然后進(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對字符串進(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; }
不斷對當(dāng)前字符串的ASCII值進(jìn)行累加運(yùn)算,里面用到了異或,左移和右移。
總結(jié)
綜上: 當(dāng)我們的業(yè)務(wù)開發(fā)中遇到狀態(tài)數(shù) >=5 并且有交叉重疊的時候就需要考慮以上兩種辦法了。
到此這篇關(guān)于js位運(yùn)算在實際中使用的文章就介紹到這了,更多相關(guān)js位運(yùn)算使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JS通過位運(yùn)算實現(xiàn)權(quán)限加解密
這篇文章主要介紹了JS通過位運(yùn)算實現(xiàn)權(quán)限加解密的相關(guān)知識,非常不錯,具有一定的參考借鑒價值,需要的朋友參考下吧2018-08-08Javascript驗證用戶輸入URL地址是否為空及格式是否正確
這篇文章主要介紹了Javascript驗證用戶輸入URL地址是否為空及格式是否正確,很實用,需要的朋友可以參考下2014-10-10BootStrap點(diǎn)擊下拉菜單項后顯示一個新的輸入框?qū)崿F(xiàn)代碼
這篇文章主要介紹了BootStrap點(diǎn)擊下拉菜單項后顯示一個新的輸入框?qū)崿F(xiàn)代碼的相關(guān)資料,需要的朋友可以參考下2016-05-05微信小程序 wx:for 與 wx:for-items 與 wx:key的正確用法
這篇文章主要介紹了微信小程序 wx:for 與 wx:for-items 與 wx:key的正確用法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-05-05js接收并轉(zhuǎn)化Java中的數(shù)組對象的方法
下面小編就為大家?guī)硪黄猨s接收并轉(zhuǎn)化Java中的數(shù)組對象的方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-08-08