Go中的bit位和位运算符

栏目: IT技术 · 发布时间: 4年前

内容简介:bit比特是计算机的最小单元,是一个二进制位1或者0主要有下面几种运算符左移 i << n; 对i的所有位向左移n次

一.二进制长什么样

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...


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Unity 3D脚本编程

Unity 3D脚本编程

陈嘉栋 / 电子工业出版社 / 2016-9-1 / 79

《Unity 3D脚本编程——使用C#语言开发跨平台游戏》以Unity 3D 的跨平台基础Mono,以及其游戏脚本语言C#为基础进行讲解。全面系统地剖析了Unity 3D 的跨平台原理以及游戏脚本开发的特点。 第1 章主要介绍了Unity 3D 引擎的历史以及编辑器的基本知识;第2 章主要介绍了Mono,以及Unity3D 利用Mono 实现跨平台的原理,并且分析了C#语言为什么更适合Uni......一起来看看 《Unity 3D脚本编程》 这本书的介绍吧!

SHA 加密
SHA 加密

SHA 加密工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具