一.二进制长什么样
bit比特是计算机的最小单元,是一个二进制位1或者0
t.Log("start")
t.Logf("%b", 0) //0
t.Logf("%b", 1) //1
t.Logf("%b", 2) //10
t.Logf("%b", 3) //11
/*
int是带符号的,表示范围是:-2147483648到2147483648,即-2^31到2^31次方。
uint则是不带符号的,表示范围是:2^32即0到4294967295。
*/
var one uint
one = 10000
t.Logf("%b", one) //10011100010000 13位,uint最多是32位
二.运算符
主要有下面几种运算符
& 位运算 AND
| 位运算 OR
^ 位运算 XOR
&^ 位清空 (AND NOT)
<< 左移
>> 右移
1.<<和>>左移和右移运算符
左移 i << n; 对i的所有位向左移n次
var i int64
t.Logf("%b", i) //0
i = 1
t.Logf("%b %d", i, i) // 1 1
t.Logf("%b %d", i<<1, i<<1) //10 2 左移动 每个移位位置代表2的幂,左移动增加
t.Logf("%b %d", i<<2, i<<2) // 100 4
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) 左移动10位 2的10次方=1024
MB // 1<<(10*2)
GB // 1<<(10*3)
TB // 1<<(10*4)
PB // 1<<(10*5)
)
2.位运算 & AND
同一位上都是1 才1 否咋0
c, d := 1, 1
t.Logf("c&d %b %b %b", c&d, c, d) //c&d 1 1 1
c, d = 1, 0
t.Logf("c&d %b %b %b", c&d, c, d) //c&d 0 1 0
c, d = 5, 3
t.Logf("c&d %b %b %b", c&d, c, d) //c&d 1 101 011
c, d = 5, 4
t.Logf("c&d %b %b %b", c&d, c, d) //c&d 100 101 100 十进制4
c, d = 50, 43
t.Logf("c&d %b %b %b", c&d, c, d) //c&d 100010 110010 101011 十进制34
1.使用案例 判断奇偶数
odd number :指不能被2整除的数 ,数学表达形式为:2k+1, 奇数可以分为正奇数和负奇
func IsOdd(i int)bool{
return (i & 1) == 1 //i是否为奇数取决于二进制的最后一位是1还是0 是1则为奇数 0则为偶数
}
2.使用案例 计算数值的二进制位有多少个1
很容易想到只要与1进行&运算,第一位如果为0结果为0 第一位如果结果为1 结果为1 利用这个特性数值右移一位 循环计算即可
func BitCheck(i int)(count int){
for i>0 {
count = count + (i&1)
i >>= 1
}
return
}
2.位运算 | OR
同一位上有一个是1就1,只有都是0才0
c, d = 0, 0
t.Logf("c|d %b %b %b", c|d, c, d) //c|d 0 0 0
c, d = 1, 1
t.Logf("c|d %b %b %b", c|d, c, d) //c|d 1 1 1
c, d = 1, 0
t.Logf("c|d %b %b %b", c|d, c, d) //c|d 1 1 0
c, d = 5, 3
t.Logf("c|d %b %b %b", c|d, c, d) //c|d 111 101 011 十进制7
c, d = 5, 4
t.Logf("c|d %b %b %b", c|d, c, d) //c|d 101 101 100 十进制5
c, d = 50, 43
t.Logf("c|d %b %b %b", c|d, c, d) //c|d 111011 110010 101011 十进制59
3.异或运算符 ^ XOR
^即可作为二元运算符,也可作为一元运算符。
作为二元运算符,^是异或运算符。
即两个数的二进制位不同时,当前位才置1 否则置0
有个很明显的规律 任何数和本身异或 结果为0, 0和任意数异或 结果为其本身
a, b := 2, 3
t.Logf("%b %b", a, b) //10 11
a ^= b
t.Logf("%b %b", a, b) // 1 11
4 ^ 15 = 11
---------------
00000100 ^
00001111 =
00001011 //10进制值位11
1.使用案例 数值交换
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互相抵消 完成了值的交换
4.位清空运算符 &^ AND NOT
4 &^ 15 = 0
---------------
00000100 &^
00001111
00000000
=0
三.二元运算符号
a |= b -----> a = a | b , a 或者 b 只要有一个为 1, 那么,a 的最终结果就为 1
a &= b -----> a = a & b , a 和 b 二者必须都为 1, 那么,a 的最终结果才为 1
a ^= b -----> a = a ^ b , 当且仅当 a 和 b 的值不一致时,a 的最终结果才为1,否则为0
a, b := 1, 0
a |= b
t.Logf("%b %b", a, b) // 1 0
a, b = 1, 0
a &= b
t.Logf("%b %b", a, b) // 0 0
a, b = 1, 0
a ^= b
t.Logf("%b %b", a, b) // 1 0
a, b = 2, 3
t.Logf("%b %b", a, b) //10 11
a |= b
t.Logf("%b %b", a, b) //11 11
a, b = 2, 3
a &= b
t.Logf("%b %b", a, b) // 10 11
a, b = 2, 3
a ^= b
t.Logf("%b %b", a, b) // 1 11
使用案例参考了作者niceshot
网页 https://juejin.im/post/5d9094...
有疑问加站长微信联系(非本文作者)