位元運算子


Posted by david-christian on 2023-04-29

運算子

  • &:兩個位元都是 1,結果為 1,否則均為 0
  • |:兩個位元其中有 1,結果為 1,否則均為 0
  • ^:兩個位元相同,結果為 1,不同,結果為 0

& 運算子範例 + 解說

package main

import (
    "fmt"
)

func main() {
    result := 3
    fmt.Print(result & 2) // 2
}

3 & 2 的結果為 2
3 的二進位表示是 0b0011
2 的二進位表示是 0b0010
從右到左,分別將兩個二進位表示的每一個位元做 & 運算
3 的二進位第一個位元為 1,2 的第一個位元為 0,結果為 0
3 的第二個位元為 1,2 的第二個位元為 1,結果為 1
兩者剩下的位元都為 0,不多贅述

          0b0011
   上下每個位元按位做 & 比較
          0b0010
   結果:  0b0010

運算的結果為 0b0010 換成十進位也就是 2。

| 運算子範例 + 解說

package main

import (
    "fmt"
)

func main() {
    result := 17
    fmt.Print(result | 23) // 23

}

17 | 23 的結果為 23
17 的二進位表示是 0b10001
23 的二進位表示是 0b10111
從右到左,分別將兩個二進位表示的每一個位元做 | 運算
17 的二進位第一個位元為 1,23 的第一個位元為 1,結果為 1
17 的第二個位元為 1,23 的第二個位元為 0,結果為 0

          0b10001
   上下每個位元按位做 & 比較
          0b10111
   結果:  0b10111

依此類推,將結果組合起來為 0b10111,十進位表示就是 23。

場景運用

假設我們現在遇到的場景是,需要判斷一些事項是否有做過
一般來說普遍的作法,可能是設定一些變數來判定這些事項

var isHandleA = false
var isHandleB = false
var isHandleC = false
var isHandleD = false

缺點就是在不同的判斷式判斷不同的變數
我們可以將位元運算子運用在這種場景上,優雅的處理

var A = 1
var B = 2
var C = 4
var D = 8
var isHandled = 0
// 如果處理 C 了
isHandled = isHandled | C // 也可以簡寫成 isHandled |= C
if ((isHandled & C) != 0) // C就是有做過的

// 為甚麼是 1 2 4 8 ?
// 1的二進位 1
// 2的二進位 10
// 4的二進位 100
// 8的二進位 1000
// 這裡選的數字的二進位都是進一個位數的
// 舉例 D 跟 C 都有做過,所以 isHandled  = 12
// 12 的二進位是 1100,所以當你要檢查 B 有沒有做過時
// 意思是 1100 & 0010 ,答案是0,所以 B 沒有做過

這樣子的寫法,或許在程式面感受不大,但試想如果你今天是有一些 Type 要存在 Database 裡
用位元運算子的寫法,只需要存一個 isHandled,其他的可以寫在程式面。


#Bitwise operation







Related Posts

Command line 基本指令

Command line 基本指令

Github page

Github page

巢狀救星三部曲(3) Async Functions

巢狀救星三部曲(3) Async Functions


Comments