位掩码和位运算在Golang中的应用

huangapple go评论76阅读模式
英文:

Bitmasking and Bitwise Operations in Golang

问题

我是你的中文翻译助手,以下是你要翻译的内容:

我对编程一般都是初学者,所以如果我在提问时犯了一些错误,我很抱歉。

我正在学习的教程涉及以下代码:

package main

import (
	"fmt"
)

const (
	isAdmin = 1 << iota
	isHeadquarters
	canSeeFinancials
	
	canSeeAfrica
	canSeeAsia
	canSeeEurope
	canSeeNorthAmerica
	canSeeSouthAmerica
)

func main() {
	var roles byte = isAdmin | canSeeFinancials | canSeeEurope
	fmt.Printf("%b\n", roles)
	fmt.Printf("Is Admin? %v\n", isAdmin & roles == isAdmin)
}

教程中的人很快提到了这部分被称为位掩码(Bitmasking)

fmt.Printf("Is Admin? %v\n", isAdmin & roles == isAdmin)

现在,据我理解,这里发生的过程大致如下:
计算机被问到是否isAdminroles都等于isAdmin,并回答true

但是,当我尝试这样做时:

fmt.Printf("Is Admin? %v\n", roles == isAdmin)

结果却是false

有人能详细解释一下这个过程背后的逻辑吗?这部分让我有点困惑,我想知道为什么会这样。谢谢。

英文:

I'm a beginner to programming in general so i'm sorry if i make some mistakes while putting this question up.

The tutorial I'm following goes over this code:

package main

import (
	&quot;fmt&quot;
)

const (
	isAdmin = 1 &lt;&lt; iota
	isHeadquarters
	canSeeFinancials
	
	canSeeAfrica
	canSeeAsia
	canSeeEurope
	canSeeNorthAmerica
	canSeeSouthAmerica
)

func main() {
	var roles byte = isAdmin | canSeeFinancials | canSeeEurope
	fmt.Printf (&quot;%b\n&quot;, roles)
	fmt.Printf (&quot;Is Admin? %v\n&quot;, isAdmin &amp; roles == isAdmin)
}

The guy in tutorial quickly mentions how this part is called Bitmasking.

fmt.Printf (&quot;Is Admin? %v\n&quot;, isAdmin &amp; roles == isAdmin)

Now, as far as i understand, the process that takes place here goes something like this:
The computer is being asked if both isAdmin and roles are equal to isAdmin and replies true.

But, when i'm trying to do this:

fmt.Printf (&quot;Is Admin? %v\n&quot;, roles == isAdmin)

It results in false.

Can somebody go in greater detail on the whole logic behind this process? This bit leaves me a bit confused and i want to know why that happens. Thank you.

答案1

得分: 10

你的角色常量都是特殊的数字,其中二进制(2的补码)表示恰好包含一个1位,其他位都是零,并且它们都不同(每个位置上的1位都不同)。这是通过将数字1左移(使用iota)来实现的。

role变量的值是通过使用按位或(bitwise OR)构建的:

var roles byte = isAdmin | canSeeFinancials | canSeeEurope

按位或保留1位,在结果中,每个操作数在该位置上包含0时,结果中将只有0位。由于所有被OR运算的值在不同的位置上都包含一个单独的1位,role将包含与OR运算的不同角色数量相同的位,并且位于它们的特殊位置。

为了更容易理解这些位,让我们打印二进制表示:

fmt.Printf("isAdmin          %08b\n", isAdmin)
fmt.Printf("canSeeFinancials %08b\n", canSeeFinancials)
fmt.Printf("canSeeEurope     %08b\n", canSeeEurope)
fmt.Printf("-------------------------\n")
fmt.Printf("roles            %08b\n", roles)

这将输出:

isAdmin          00000001
canSeeFinancials 00000100
canSeeEurope     00100000
-------------------------
roles            00100101

如你所见,roles在任何上述位模式中有1的位置上都包含1

当你使用按位与(掩码)时,如果给定位置上的任何输入位为0,结果位将为0,只有当两个位都为1时,结果位才为1

表达式:

isAdmin & roles

由于isAdmin包含一个单独的1位,上述掩码将是一个数字,最多也只能包含一个单独的1位,只有当roles在该位置上有一个1位时。实际上,这个掩码告诉我们roles是否包含isAdmin位。如果包含,结果将是一个等于isAdmin的值。如果不包含,结果将是一个由所有0位组成的数字,即十进制0

再次可视化这些位:

fmt.Printf("roles            %08b\n", roles)
fmt.Printf("isAdmin          %08b\n", isAdmin)
fmt.Printf("-------------------------\n")
fmt.Printf("isAdmin & roles  %08b\n", isAdmin&roles)

输出:

roles            00100101
isAdmin          00000001
-------------------------
isAdmin & roles  00000001

Go Playground上尝试这些示例。

因此,表达式:

isAdmin & roles == isAdmin

如果roles包含(包括)isAdmin角色,则为true,否则为false

如果没有进行掩码操作:

roles == isAdmin

如果roles等于isAdmin,即它只包含isAdmin角色和没有其他角色,那么结果将为true。如果它包含其他角色,显然它将不等于isAdmin

英文:

All your role constants are special numbers where the binary (2's complement) representation contains exactly a single 1 bit, all other bits are zeros, and they are all different (the 1 bit is in a different position in each). This is achieved by shifting the 1 number to the left with increasing values (iota).

The role variable's value is constructed by using bitwise OR:

var roles byte = isAdmin | canSeeFinancials | canSeeEurope

Bitwise OR keeps 1 bits, and in the result there will only be 0 bits where each operand contains 0 in that position. Since all values being OR'ed contain a single 1 bit in different positions, role will contain as many bits as many different roles OR'ed, and at their special positions.

To easily understand the bits, let's print the binary representations:

fmt.Printf(&quot;isAdmin          %08b\n&quot;, isAdmin)
fmt.Printf(&quot;canSeeFinancials %08b\n&quot;, canSeeFinancials)
fmt.Printf(&quot;canSeeEurope     %08b\n&quot;, canSeeEurope)
fmt.Printf(&quot;-------------------------\n&quot;)
fmt.Printf(&quot;roles            %08b\n&quot;, roles)

This will output:

isAdmin          00000001
canSeeFinancials 00000100
canSeeEurope     00100000
-------------------------
roles            00100101

As you can see, roles contains 1s where any of the above bit patterns has 1.

When you use bitwise AND (masking), the result bit will be 0 if any of the input bit is 0 at a given position, and will be 1 only if both bits are 1s.

The expression:

isAdmin &amp; roles

Since isAdmin contains a single 1 bit, the above masking will be a number that may also contain a single 1 bit at most, only if roles has a 1 bit at that position. Effectively this masking tells if roles contains the isAdmin bit. If it contains it, the result will be a value equal to isAdmin. If not, the result will be a number consisting all 0 bits, that is: decimal 0.

Visualizing the bits again:

fmt.Printf(&quot;roles            %08b\n&quot;, roles)
fmt.Printf(&quot;isAdmin          %08b\n&quot;, isAdmin)
fmt.Printf(&quot;-------------------------\n&quot;)
fmt.Printf(&quot;isAdmin &amp; roles  %08b\n&quot;, isAdmin&amp;roles)

Output:

roles            00100101
isAdmin          00000001
-------------------------
isAdmin &amp; roles  00000001

Try the examples on the Go Playground.

So the expression:

isAdmin &amp; roles == isAdmin

Will be true if roles contains (includes) the isAdmin role, false otherwise.

Without masking:

roles == isAdmin

This will be true if roles equals to isAdmin, that is, if it only contains the isAdmin role and nothing else. If it contains other roles, it obviously won't be equal to isAdmin.

huangapple
  • 本文由 发表于 2021年7月29日 20:16:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/68575772.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定