WeHelp
位元運算簡介 Bitwise Operators
2025-04-09 12:13:52
## 什麼是位元運算 位元運算符號 ( Bitwise Operators ) 可以針對整數中的每一個位元進行獨立運算。為了理解位元運算的概念,我們首先要知道如何把整數拆解成二進位的位元表示法,然後才能進一步探討後續的細節。因此,本文將按照以下順序和大家介紹位元運算的概念和應用。 - 如何將整數 ( Integer ) 轉換為二進位表示法 - 基本的 AND 和 OR 位元運算 - 位元運算在權限控制上的應用 ---- ## 如何將整數轉換為二進位表示法 相較於平常熟悉的十進位表示法,可以使用 0 ~ 9 十個符號來表達數字;在二進位表示法中,我們只能夠使用 0 和 1 兩個符號來表達數字。 為了簡化概念,以非負整數為例,參考以下十進位與二進位的對應表。 | 十進位 | 二進位 | 說明 | |---|---|---| | 0 | 0 | 沒什麼不一樣 | | 1 | 1 | | | 2 | 10 | 無法用單一符號表示 2,所以 1 + 1 必須進位到第二格,等於 10,讀做壹零 | | 3 | 11 | | | 4 | 100 | 3 + 1 = 4 對應到 11 + 1 = 100:第一格進位到第二格,第二格進位到第三格 | | 5 | 101 | | | 6 | 110 | | | 7 | 111 | | | 8 | 1000 | 7 + 1 = 8 對應到 111 + 1 = 1000 | | 9 | 1001 | | | 10 | 1010 | | ---- ## 基本的 AND 和 OR 位元運算 最基本也最常見的兩個位元運算,分別是: - AND:在 Python、JavaScript、Java 以及多數程式語言中,使用單一的 & 符號表達。 - OR:在 Python、JavaScript、Java 以及多數程式語言中,使用單一的 | 符號表達。 這兩個運算符號,都要先把整數以二進位表達後,按照順序,針對每一個位元去做運算,舉例如下: | 十進位表示法 | 二進位分解 | 說明 | |---|---|---| | 5 | 1 0 1 | | | 3 | 0 1 1 | | | 5 & 3 | 0 0 1 | 同一個位元上的兩個符號皆為 1,才會得到 1,否則是 0 | | 5 \| 3 | 1 1 1 | 同一個位元上的兩個符號皆為 0,才會得到 0,否則是 1 | 參考上表的資訊和說明: - 5 & 3 用二進位表示法,會算出 001,轉換為十進位,答案就是 1。 - 5 \| 3 用二進位表示法,會算出 111,轉換為十進位,答案就是 7。 大家可以寫簡單的程式去驗證: JavaScript: ``` javascript console.log(5 & 3); console.log(5 | 3); ``` Python: ``` python print(5 & 3) print(5 | 3) ``` ---- ## 位元運算在權限控制上的應用 學習位元運算並不難,但許多人好奇的是這樣的運算到底可以用在什麼實際的場景中?常見的應用場景包括: - 用來做資料正確性的檢測,有興趣的朋友可以搜尋 Checksum 演算法。 - 用來做權限的控制。 我們來談談第二個應用。 一般來說,如果我們要記錄使用者擁有哪些權限,可以為每一個權限設計一個獨立的欄位,並記錄使用者是否具備該權限,參考設計表如下: | 使用者名稱 | 管理 | 寫入 | 讀取 | |---|---|---|---| | 彭彭 | 1 | 1 | 1 | | 丁滿 | 0 | 0 | 1 | | 辛巴 | 0 | 1 | 1 | 分開成三個欄位來紀錄資料,在儲存、讀寫時,有時候會產生多餘的浪費。雖然這個浪費在很多時候微不足道,但在極端或特定限制的情境中,我們可以考慮用單一的整數來記錄多種權限的開關,並利用 Bitwise 位元運算來判斷每個權限的開關,參考設計表如下: | 使用者名稱 | 權限紀錄 | 說明 | |---|---|---| | 彭彭 | 7 | 二進位 111 每個位元代表一個權限開關,權限全開 | | 丁滿 | 1 | 二進位 001 每個位元代表一個權限開關,僅讀取權限 | | 辛巴 | 3 | 二進位 011 每個位元代表一個權限開關,僅讀取寫入權限 | 然而,我們要如何從一個單一整數的紀錄中,判斷特定權限是否打開或關閉呢?以寫入權限的判斷為例,搭配 Bitwise 位元運算進行: | 使用者名稱 | 權限紀錄 | 二進位表示法 | 判斷是否有寫入權限 | |---|---|---|---| | 彭彭 | 7 | 111 | 判斷 111 & 010 是否為 010,是的 | | 丁滿 | 1 | 001 | 判斷 001 & 010 是否為 010,不是 | | 辛巴 | 3 | 011 | 判斷 011 & 010 是否為 010,是的 | 如上表,以辛巴為例,權限紀錄是 3,要判斷是否具備寫入權限,只要使用簡單的判斷式 3 & 2 == 2 ( 011 & 010 是否為 010 ) 即可。程式碼的邏輯如下: JavaScript: ``` javascript const WRITE_ACCESS_MASK = 2; // 二進位 010 let rights = 7; // 取得某個使用者的權限資料 if(rights & WRITE_ACCESS_MASK === WRITE_ACCESS_MASK){ console.log("具備寫入權限"); } ``` Python: ``` python WRITE_ACCESS_MASK = 2 # 二進位 010 rights = 7 # 取得某個使用者的權限資料 if rights & WRITE_ACCESS_MASK == WRITE_ACCESS_MASK: print("具備寫入權限") ``` ---- ### 小結 我們在寫應用程式時,相對比較少使用位元運算,但這樣一個不侷限於特定程式語言的思維和技巧,在很多底層邏輯中默默地發揮關鍵作用,希望本文可以幫助大家建立對於位元運算的基本理解。