Go 位運算符的使用
位運算在平時寫代碼時不常用到,但是在很多的官方和非官方的優秀代碼中經常會看到,被這些位運算的操作所驚豔。如果在平時的擼代碼過程中,能夠用到提升性能的位運算同時代碼也顯得很簡潔,那何樂不爲呢。
下面簡單介紹下各個運算符以及可能會使用到的場景
二元運算符
-
& 與運算符 AND
當兩個數二進制位同爲 1 的時候當前位置 1,否則置 0
4 & 15 = 4
---------------
00000100 &
00001111
00000100
=4
位運算的使用場景
-
判斷奇偶數
常見的代碼中可能是這樣的
func IsOdd(i int)bool{
return i%2!=0
}
位運算判斷
func IsOdd(i int)bool{
return (i & 1) == 1 //i 是否爲奇數取決於二進制的最後一位是 1 還是 0 是 1 則爲奇數 0 則爲偶數
}
-
計算數值的二進制位有多少個 1
很容易想到只要與 1 進行
&運算
, 第一位如果爲 0 結果爲 0 第一位如果結果爲 1 結果爲 1 利用這個特性數值右移一位 循環計算即可
func BitCheck(i int)(count int){
for i>0{
count = count + (i&1)
i >>= 1
}
return
}
如果數值中間有多個 0 需要多次判斷,優化方法是值 x 如果不爲 0 那麼和`x-1`進行與操作就會找出最低位的 1
/*
10110001 & //初始值
10110000 //減 1 後
=10110000 & //找出最低位的 1
10101111 //繼續減 1
=10100000 //找出最低位的 1
.... //直到找不出 1 即爲 0
*/
func BitCheck(i int)(count int){
for i>0{
count += 1
i &= i-1
}
return
}
-
| 或運算符 OR
當兩個數二進制位有一個爲 1 時當前位置 1,同爲 0 的時候當前位纔會置 0
4 | 15 = 15
---------------
00000100 |
00001111
=15
-
^ 異或運算符 XOR
^ 即可作爲二元運算符,也可作爲一元運算符。
作爲二元運算符,^ 是異或運算符。
即兩個數的二進制位不同時,當前位才置 1 否則置 0
有個很明顯的規律 任何數和本身異或 結果爲 0, 0 和任意數異或 結果爲其本身
4 | 15 = 11
---------------
00000100 ^
00001111
00001011
=11
例子
-
數值交換
Go 中數值交換可以直接通過
a, b = b, a
這樣的方式來直接交換,位運算是怎麼實現交換的呢?
a ^= b // a = a^b
b ^= a // b = b^(a^b) b 和 b 自己異或爲 0 相當於 b=a
a ^= b // a = (a^b)^a a 在第一步中已經爲 a^b,現在的 b 已經等於 a a 互相抵消 完成了值的交換
-
尋找列表中只出現一次的數字
假如一個列表中有 2*N+1 個數,其中一個數字只出現了一次。其他的數都出現了兩次。如何尋找這個數字
利用
任何數和自己異或的結果將爲 0 的特性
func SingleNum(list []int)(target int){
target = list[0]
for _,val:=range list[1:]{
target ^= val
}
return
}
-
&^ 位清空運算符 AND NOT
看一個列子
4 &^ 15 = 11
---------------
00000100 &^
00001111
00000000
=0
位清空的意思是 假如有 兩個變量 var1 &^ var2 作位清空運算
-
如果 var2 變量的位爲 0 則取 var1 變量對應的位值作爲結果位
-
如果 var2 變量的位爲 1 則結果位取 0
-
<<和>> 左移和右移運算符
兩個運算符左側總是爲要進行位移操作的變量,右側爲需要移動的位數值。
之前因爲看到 32<<0=32 就有點懵,以爲是 0 左移 32 位 不明白爲什麼結果爲 32,就是因爲把 32 當做要位移的位數了。
1<<N = 2^N
-----------
1 左移多少位等於 2 的多少次方
1024>>N = 1024/2^N
---------------
右移 N 位 相當於除以 2 的 N 次方
關於左移、右移 , 有一個 Go 在寫磁盤單位 GB MB KB 等大小定義的例子
在使用const
關鍵字的時候 可使用內置變量 iota
從 0 開始自動遞增
在遇到下個常量塊或者單個常量定義的時候 也就是再一次使用 const 關鍵字的時候 iota 置 0
package main
type ByteSize float64
const(
B ByteSize = 1<<(10*iota) // 1<<(10*0)
KB // 1<<(10*1)
MB // 1<<(10*2)
GB // 1<<(10*3)
TB // 1<<(10*4)
PB // 1<<(10*5)
)
轉自:
juejin.cn/post/6844903955718225928
Go 開發大全
參與維護一個非常全面的 Go 開源技術資源庫。日常分享 Go, 雲原生、k8s、Docker 和微服務方面的技術文章和行業動態。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/8wubPDKO6-CLLhqjGsJ7xw