【问题标题】:Bitmasking and Bitwise Operations in GolangGolang 中的位掩码和位运算
【发布时间】:2021-10-05 02:27:25
【问题描述】:

我是一般编程的初学者,所以如果我在提出这个问题时犯了一些错误,我很抱歉。

我正在关注的教程介绍了这段代码:

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

有人可以更详细地了解这个过程背后的整个逻辑吗?这一点让我有点困惑,我想知道为什么会这样。谢谢。

【问题讨论】:

  • &amp;bitwise AND,而 &amp;&amp; 是逻辑与。您所描述的是isAdmin == isAdmin &amp;&amp; roles == isAdmin(这没有多大意义)。链接的维基百科页面详细介绍了位掩码。请仔细阅读。

标签: go bitwise-operators boolean-logic bitmask


【解决方案1】:

所有角色常量都是特殊数字,其中二进制(2 的补码)表示正好包含一个 1 位,所有其他位都是零,并且它们都是不同的(1 位在每个)。这是通过将 1 数字向左移动值增加 (iota) 来实现的。

role 变量的值是使用按位或构造的:

var roles byte = isAdmin | canSeeFinancials | canSeeEurope

按位或保留1 位,结果将只有0 位,其中每个操作数在该位置包含0。由于所有被 OR'ed 的值在不同的位置都包含一个 1 位,所以role 将包含尽可能多的不同角色 OR'ed 的位,并且在它们的特殊位置。

为了便于理解位,让我们打印二进制表示:

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 包含1s,而上述任何位模式都包含1

当您使用按位与(屏蔽)时,如果任何输入位在给定位置为0,则结果位将为0,并且仅当两个位均为1s 时才会为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

【讨论】:

  • 谢谢!虽然位掩码的概念仍然很难理解,但提供的代码现在更容易理解了!我会花时间更彻底地研究遮罩,以便更好地理解它。
  • @Sinoreth 添加了位的可视化表示,使其更易于理解。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-26
  • 2016-02-20
相关资源
最近更新 更多