返回顶部
首页 > 资讯 > 后端开发 > GO >浅析Golang中的的位操作(按位运算符)
  • 358
分享到

浅析Golang中的的位操作(按位运算符)

位操作go语言Golang 2023-05-14 19:05:24 358人浏览 独家记忆
摘要

在计算机内存昂贵,处理能力有限的美好旧时光里,用比较黑客范的位运算方式去处理信息是首选方式(某些情况下只能如此)。时至今日,直接使用位运算仍然是很多计算领域中不可或缺的部分,例如底层系统编程,图形处理,密码学等。Go 编程语言支持以下按位运

浅析Golang中的的位操作(按位运算符)

在计算机内存昂贵,处理能力有限的美好旧时光里,用比较黑客范的位运算方式去处理信息是首选方式(某些情况下只能如此)。时至今日,直接使用位运算仍然是很多计算领域中不可或缺的部分,例如底层系统编程,图形处理,密码学等。

Go 编程语言支持以下按位运算符:

&   bitwise AND
 |   bitwise OR
 ^   bitwise XOR
&^   AND NOT
<<   left shift
>>   right shift

本文的余下部分详述了每个操作符以及它们如何使用的案例。

& 运算符

在 Go 中, & 运算符在两个整型操作数中执行按位 AND 操作。AND 操作具有以下属性:

Given operands a, b
AND(a, b) = 1; only if a = b = 1
               else = 0

AND 运算符具有选择性的把整型数据的位清除为 0 的好的效果。 例如,我们可以使用 & 运算符去清除(设置)最后 4 个最低有效位(LSB)全部为 0 。

func main() {
    var x uint8 = 0xAC    // x = 10101100
    x = x & 0xF0          // x = 10100000
}

所有的位运算都支持简写的赋值形式。 例如,前面的例子可以重写为如下。

func main() {
    var x uint8 = 0xAC    // x = 10101100
    x &= 0xF0             // x = 10100000
}

另外一个巧妙的技巧是:你可以用 & 操作去测试一个数字是奇数还是偶数。原因是当一个数字的二进制的最低位是 1 的时候,那他就是奇数。我们可以用一个数字和 1 进行 & 操作,然后在和 1 做 AND 运算,如果的到的结果是 1 ,那么这个原始的数字就是奇数

import (
    "fmt"
    "math/rand"
)
func main() {
    for x := 0; x < 100; x++ {
        num := rand.Int()
        if num&1 == 1 {
            fmt.Printf("%d is odd\n", num)
        } else {
            fmt.Printf("%d is even\n", num)
        }
    }
}

在 Playground 上运行上面的例子

| 操作符

| 对其整型操作数执行按位操作。回想一下操作符具备以下性质:

Given operands a, b
OR(a, b) = 1; when a = 1 or b = 1
              else = 0

我们可以利用按位操作符为给定的整数有选择地设置单个位。例如,在如下示例中我们使用按位将示例数(从低位到高位(MSB))中的第 3 ,第 7 和第 8 位置为 1 。

func main() {
    var a uint8 = 0
    a |= 196
    fmt.Printf("%b", a)
}

// 打印结果  11000100
            ^^   ^

练习场中可运行范例。

在使用位掩码技术为给定的整型数字设置任意位时,运算非常有用。例如,我们可以扩展之前的程序为变量 a 存储的值设置更多的位。

func main() {
    var a uint8 = 0
    a |= 196
    a |= 3
    fmt.Printf("%b", a)
}

// 打印结果 11000111

在练习场中可以运行范例。

在前面的程序里,不仅要按位设置十进制的 196,而且要设置低位上的十进制 3。我们还可以继续(上更多的值)设置完所有的位。

位运算的配置用法

现在,回顾一下 AND(a, 1) = a 当且仅当 a = 1。 我们可以利用这个特性去查询其设置位的值。例如,在上述代码中 a & 196 会返回 196 是因为这几位的值在 a 中确实都存在。所以我们可以结合使用 ORAND 运算的方式来分别设置和读取某位的配置值。.

接下来的源码片段演示了这个操作。函数 procstr 会转换字符串的内容。它需要两个参数:第一个, str,是将要被转换的字符串,第二个, conf,是一个使用位掩码的方式指定多重转换配置的整数。

const (
    UPPER  = 1 // 大写字符串
    LOWER  = 2 // 小写字符串
    CAP    = 4 // 字符串单词首字母大写
    REV    = 8 // 反转字符串
)

func main() {
    fmt.Println(procstr("HELLO PEOPLE!", LOWER|REV|CAP))
}

func procstr(str string, conf byte) string {
    // 反转字符串
    rev := func(s string) string {
        runes := []rune(s)
        n := len(runes)
        for i := 0; i < n/2; i++ {
            runes[i], runes[n-1-i] = runes[n-1-i], runes[i]
        }
        return string(runes)
    }

    // 查询配置中的位操作
    if (conf & UPPER) != 0 {
        str = strings.ToUpper(str)
    }
    if (conf & LOWER) != 0 {
        str = strings.ToLower(str)
    }
    if (conf & CAP) != 0 {
        str = strings.Title(str)
    }
    if (conf & REV) != 0 {
        str = rev(str)
    }
    return str
}

在 Playground上面运行代码.

上面的 procstr("HELLO PEOPLE!", LOWER|REV|CAP) 方法会把字符串变成小写,然后反转字符串,最后把字符串里面的单词首字母变成大写。这个功能是通过设置 conf 里的第二,三,四位的值为 14 来完成的。然后代码使用连续的 if 语句块来获取这些位操作进行对应的字符串转换。

^ 操作符

在 Go 中 按位 异或 操作是用 ^ 来表示的。 异或运算符有如下的特点:

Given operands a, b
XOR(a, b) = 1; only if a != b
     else = 0

异或运算的这个特性可以用来把二进制位的一个值变成另外一个值。举个例子,给到一个 16 进制的值,我们可以使用以下代码切换前8位(从 MSB 开始)的值。

func main() {
    var a uint16 = 0xCEFF
    a ^= 0xFF00 // same a = a ^ 0xFF00
}

// a = 0xCEFF   (11001110 11111111)
// a ^=0xFF00   (00110001 11111111)

在前面的代码片段中,与 1 进行异或的位被翻转(从 0 到 1 或从 1 到 0)。异或 运算的一个实际用途,例如,可以利用 异或运算去比较两个数字的符号是否一样。当 (a ^ b) ≥ 0 (或相反符号的 (a ^ b) < 0 )为 true 的时候,两个整数 a,b 具有相同的符号,如下面的程序所示:

func main() {
    a, b := -12, 25
    fmt.Println("a and b have same sign?", (a ^ b) >= 0)
}

在 Go 的 Playground运行代码。

当执行上面这个程序的时候,将会打印出:a and b have same sign? false。在 Go Playground 上修改程序里 a ,b 的符号,以便看到不同的结果。

^ 作为取反位运算符 (非)

不像其他语言 (C/C++,Java,pythonjavascript,等), Go 没有专门的一元取反位运算符。取而代之的是,XOR 运算符 ^,也可作为一元取反运算符作用于一个数字。对于给定位 x,在 Go 中 x = 1 ^ x 可以翻转该位。在以下的代码段中我们可以看到使用 ^a 获取变量 a 的取反值的操作。

func main() {
    var a byte = 0x0F
    fmt.Printf("%08b\n", a)
    fmt.Printf("%08b\n", ^a)
}

// 打印结果
00001111     // var a
11110000     // ^a

在练习场中可以运行范例。

&^ 操作符

&^ 操作符意为 与非,是 操作符的简写形式,它们定义如下。

Given operands a, b
AND_NOT(a, b) = AND(a, NOT(b))

如果第二个操作数为 1 那么它则具有清除第一个操作数中的位的趣味特性。

AND_NOT(a, 1) = 0; clears a
AND_NOT(a, 0) = a;

接下来的代码片段使用 AND NOT 操作符,将变量值1010 1011变为 1010 0000,清除了操作数上的低四位。

func main() {
    var a byte = 0xAB
     fmt.Printf("%08b\n", a)
     a &^= 0x0F
     fmt.Printf("%08b\n", a)
}

// 打印:
10101011
10100000

在练习场中运行范例。

<< 和 >> 操作符

与其他 C 的衍生语言类似, Go 使用 <<>> 来表示左移运算符和右移运算符,如下所示:

Given integer operands a and n,
a << n; shifts all bits in a to the left n times
a >> n; shifts all bits in a to the right n times

例如,在下面的代码片段中变量 a00000011)的值将会左移位运算符分别移动三次。每次输出结果都是为了说明左移的目的。

func main() {
    var a int8 = 3
    fmt.Printf("%08b\n", a)
    fmt.Printf("%08b\n", a<<1)
    fmt.Printf("%08b\n", a<<2)
    fmt.Printf("%08b\n", a<<3)
}

// 输出的结果:
00000011
00000110
00001100
00011000

在 Playground 运行代码

注意每次移动都会将低位右侧补零。相对应,使用右移位操作符进行运算时,每个位均向右方移动,空出的高位补零,如下示例 (有符号数除外,参考下面的算术移位注释)。

func main() {
 var a uint8 = 120
 fmt.Printf("%08b\n", a)
 fmt.Printf("%08b\n", a>>1)
 fmt.Printf("%08b\n", a>>2)
}

// 打印:
01111000
00111100
00011110

在 练习场中可以运行范例。

可以利用左移和右移运算中,每次移动都表示一个数的 2 次幂这个特性,来作为某些乘法和除法运算的小技巧。例如,如下代码中,我们可以使用右移运算将 200(存储在变量 a 中)除以 2 。

func main() {
    a := 200
    fmt.Printf("%d\n", a>>1)
}

// 打印:
100

在 练习场 中可以运行范例。

或是通过左移 2 位,将一个数乘以4:

func main() {
    a := 12
    fmt.Printf("%d\n", a<<2)
}
// 打印:

48

在 练习场 中可以运行范例。

位移运算符提供了有趣的方式处理二进制值中特定位置的值。例如,下列的代码中,|<< 用于设置变量 a 的第三个 bit 位。

func main() {
    var a int8 = 8
    fmt.Printf("%08b\n", a)
    a = a | (1<<2)
    fmt.Printf("%08b\n", a)
}
// prints:
00001000
00001100

可以在 练习场 中运行代码示例。

或者,您可以组合位移运算符和 & 测试是否设置了第n位,如下面示例所示:

func main() {
    var a int8 = 12
    if a&(1<<2) != 0 {
        fmt.Println("take action")
    }
}

// 打印:
take action

在 练习场中运行代码。

使用 &^ 和位移运算符,我们可以取消设置一个值的某个位。例如,下面的示例将变量 a 的第三位置为 0 :

func main() {
    var a int8 = 13 
    fmt.Printf("%04b\n", a)
    a = a &^ (1 << 2)
    fmt.Printf("%04b\n", a)
}

// 打印:
1101
1001

在 练习场 中运行代码。

关于算术位移运算的笔记

当要位移的值(左操作数)是有符号值时,Go 自动应用算术位移。在右移操作期间,复制(或扩展)二进制补码符号位以填充位移的空隙。

总结

与其它现代运算符一样,Go 支持所有二进制位操作运算符。这篇文章仅仅提供了可以用这些操作符完成的各种黑科技示例。你可以在网络上找到很多文章,特别是 Sean Eron Anderson 写的 Bit Twiddling Hacks 。

关注 Vladim @vladimirvivien 的 Twitter。

如果你正在学习 Go,阅读 Vladimir Vivien 关于 Go 的书,名为 Learning Go Programming 。

这篇文章开始由作者 Vladimir Vivien 发布在 Medium 上,名为 Bit Hacking with Go。

原文地址:https://dev.to/vladimirvivien/bit-hacking-with-go

译文地址:Https://learnku.com/go/t/23460/bit-operation-of-go

以上就是浅析golang中的的位操作(按位运算符)的详细内容,更多请关注编程网其它相关文章!

您可能感兴趣的文档:

--结束END--

本文标题: 浅析Golang中的的位操作(按位运算符)

本文链接: https://lsjlt.com/news/203667.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 浅析Golang中的的位操作(按位运算符)
    在计算机内存昂贵,处理能力有限的美好旧时光里,用比较黑客范的位运算方式去处理信息是首选方式(某些情况下只能如此)。时至今日,直接使用位运算仍然是很多计算领域中不可或缺的部分,例如底层系统编程,图形处理,密码学等。Go 编程语言支持以下按位运...
    99+
    2023-05-14
    位操作 go语言 Golang
  • Python 位操作运算符
    & 按位与运算符:参与运算的两个值,如果两个相应位都为1,则该位的结果为1,否则为0 (a & b) 输出结果 12 ,二进制解释: 0000 1100 | 按位或运算符:只要对应的二个二进位有一个为1时,结果位就...
    99+
    2023-01-30
    运算符 操作 Python
  • JavaScript的按位运算符有哪些
    本篇内容主要讲解“JavaScript的按位运算符有哪些”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“JavaScript的按位运算符有哪些”吧!JavaScr...
    99+
    2024-04-02
  • 一文浅析Golang中的运算符
    本篇文章带大家学习一下Golang,聊聊Go语言基础中的运算符,希望对大家有所帮助。Go 语言内置的运算符有:算术运算符关系运算符逻辑运算符赋值运算符位运算符对于有过其他编程语言的朋友,学习起来还是很简单的。基本上看一遍就足够了。【相关推荐...
    99+
    2023-05-14
    运算符 后端 Go
  • JavaScript位运算符怎么运算的
    JavaScript中的位运算符用于对数字的二进制表示进行操作。下面是常见的位运算符及其运算方式:1. 按位与(&):对两个数字的每...
    99+
    2023-10-11
    JavaScript
  • Java中的位运算符全解
    目录1. &(按位与运算符)2. |(按位或运算符)3. ^(异或运算符)4. <<(左移运算符)5. >> (右移移运算符)6. ~(取反运算符)7...
    99+
    2024-04-02
  • C++中的位运算和位图bitmap解析
    目录位运算总结移位运算位运算应用举例位图位运算总结 移位运算 移位运算是双目运算符,两个运算分量都是整形,结果也是整形。“<<” 左移:右边空出的...
    99+
    2024-04-02
  • c语言中的移位运算符
    移位运算符在程序设计中,是位操作运算符的一种。移位运算符可以在二进制的基础上对数字进行平移。 c语言中提供了两种移位运算符: 左移运算符:<< 右移运算符:>&...
    99+
    2024-04-02
  • C#中的位运算符怎么用
    本文小编为大家详细介绍“C#中的位运算符怎么用”,内容详细,步骤清晰,细节处理妥当,希望这篇“C#中的位运算符怎么用”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。实例请看下面的实例,了解 C# 中所有可用的位运算...
    99+
    2023-06-17
  • Java中的位运算与移位运算详解
    目录位运算按位“与” &按位“或” |异或 ^移位运算左移 <<右移 >>无符号右移 >>>总结位运算 按位“与” & ...
    99+
    2024-04-02
  • Java 中的位运算与移位运算详解
    位运算和移位运算是 Java 中常用的运算符,用于对数字的位进行操作。下面是位运算与移位运算的详细解释:1. 位运算符:- 按位与(...
    99+
    2023-08-14
    Java
  • c语言中移位运算符的示例分析
    这篇文章主要介绍c语言中移位运算符的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!C语言是什么C语言是一门面向过程的、抽象化的通用程序设计语言,广泛应用于底层开发,使用C语言可以以简易的方式编译、处理低级存储...
    99+
    2023-06-15
  • Java中的位运算与移位运算有哪些
    本篇内容介绍了“Java中的位运算与移位运算有哪些”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!位运算按位“与” &规则: 如果两个...
    99+
    2023-06-22
  • 深入解析Python运算符:比较运算符、逻辑运算符、位运算符的用途和含义
    Python运算符解析:比较运算符、逻辑运算符、位运算符的用法和意义 一、比较运算符比较运算符用于比较两个值之间的关系,并返回一个布尔值(True或False)。下面是常见的比较运算符: 等于(==): 判断两个值是否相等,如...
    99+
    2024-01-20
    逻辑 运算符 比较
  • JS中位运算符的一些妙用
    目录前言:1. 使用左移运算符 << 迅速得出2的次方2. 使用 ^ 切换变量 0 或 13. 使用 & 判断奇偶性4. 使用 !! 将数字转为布尔值5. 使用~...
    99+
    2024-04-02
  • javascript中位运算符指的是什么
    本篇内容介绍了“javascript中位运算符指的是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成! ...
    99+
    2024-04-02
  • 一文详解Golang中的位操作
    本篇文章带大家深入了解下Golang中的位操作,介绍一下详述每个操作符以及它们如何使用的案例,希望对大家有所帮助!php零基础到就业直播视频课:进入学习全程直播 + 实战授课 + 边学 + 边练 + 边辅导【推荐】《接口如何自动化测试?单流...
    99+
    2024-04-02
  • 浅谈python中的占位符
    占位符,顾名思义就是插在输出里站位的符号。我们可以把它理解成我们预定饭店。当我们告诉饭店的时候,饭店的系统里会有我们的预定位置。虽然我们现在没有去但是后来的顾客就排在我们后面。 常见的占位符有三种:   1...
    99+
    2022-06-04
    浅谈 python
  • 详解Java的位操作符
    Java的位操作符用来操作整数基本数据类型中的单个“比特”(bit),即代进制位。而我们知道比特就是0和1,那么,位操作就是对这些数据进行基本的操作。如果基本类型是char、byte或者short类型的数值进行移位处理,那么会转化成int类...
    99+
    2023-05-31
    java 操作符
  • Java中的位运算与移位运算有什么不同
    位运算和移位运算都是Java中常用的操作符,但它们执行的操作是不同的。位运算(bitwise operation)是直接对操作数的每...
    99+
    2023-08-15
    Java
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作