【问题标题】:Do bitwise values have to be exponential?按位值必须是指数的吗?
【发布时间】:2013-02-21 14:54:05
【问题描述】:

在所有按位示例中,我看到值呈指数增长(1、2、4、8 等)。但是,在下面的枚举中,我使用 1、2、3、4(如果你愿意,请原谅 VB):

<Flags()>
Enum BitWiseTest
    One = 1
    Two = 2
    Three = 3
    Four = 4
End Enum

令我惊讶的是,以下代码有效:

Dim TestBits As BitWiseTest

TestBits = TestBits Or BitWiseTest.One
TestBits = TestBits Or BitWiseTest.Two
TestBits = TestBits Or BitWiseTest.Three
TestBits = TestBits Or BitWiseTest.Four

Dim BitToRemove As BitWiseTest

BitToRemove = BitWiseTest.Two

TestBits = Not BitToRemove

Console.WriteLine(TestBits And BitToRemove)

注释掉TestBits = Not BitToRemove 行会告诉你,不删除该位会告诉你它仍然存在。将 BitToRemove = BitWiseTest.Two 更改为使用另一个枚举值将表明它也适用于其他位。

它似乎工作得完美无缺,那么我在各处看到的关于按位的值的指数递增是怎么回事?

【问题讨论】:

  • 您是否检查过如果同时设置OneTwo 会发生什么?或者当您设置Three 并取消设置One 时?
  • 啊,设置三和取消设置一破坏了它!我今天用 bitwise 学到了一些东西。

标签: .net bit-manipulation bitwise-operators


【解决方案1】:

它似乎完美无缺

这取决于您所说的“完美无缺”。

真的想要BitWiseTest.OneBitwiseTest.Two等于BitwiseTest.Three吗?这就是你现在会得到的,这通常不是理想的......通常你希望标志是独立的,这意味着它们需要由二进制表示中的独立位表示 - 而这正是你得到的通过使用 1、2、4、8、16 等值。

【讨论】:

  • 正如 CodesInChaos 的回答所证明的那样,这似乎不是它是否理想的问题,而是导致按位运算的问题,因此根本无法正常工作。设置三个并删除一个然后检查三个结果是两个,而我原本预计它会导致三个。
  • @oscilatingcretin 那里的按位运算仍然正常工作,你只是让他们做了一些不符合你意图的事情
  • @oscilatingcretin:这里使用“ideal”有点讽刺——尽管在某些情况下你确实确​​实想要组合。以NumberStyles.HexNumber 为例。按位运算“正常工作” - 当您了解它们的作用时,它们的行为符合预期。但是您确实需要先了解它们...
【解决方案2】:

一般有两种枚举。对于枚举:

  1. 使用其中一个值。
  2. 使用了值的组合。

使用其中一个值

在这种情况下,您可以随意对枚举成员进行编号。如果它们的含义相同,您甚至可以拥有两个具有相同值的成员。例如:

Enum Comparison
    None = 0
    CaseSensitive = 1
    IgnoreCase = 2

    Default = 1
End Enum

使用了值的组合

一个值现在是布尔值:它要么是on(使用,指定)或off(未使用或指定)。这很好地转换为位,即 1(开)或 0(关)。为了能够将这些值彼此区分开来,您应该使用 2 的幂。那么对于任何特定位,只有一个值可以设置该位的开或关。

<Flags()>
Enum NumberStyles
    None = 0                    ' Binary:          0
    AllowLeadingWhite = 1       ' Binary:          1
    AllowTrailingWhite = 2      ' Binary:         10
    AllowLeadingSign = 4        ' Binary:        100
    AllowTrailingSign = 8       ' Binary:       1000
    AllowParentheses = 16       ' Binary:      10000
    AllowDecimalPoint = 32      ' Binary:     100000
    AllowThousands = 64         ' Binary:    1000000
    AllowExponent = 128         ' Binary:   10000000
    AllowCurrencySymbol = 256   ' Binary:  100000000
    AllowHexSpecifier = 512     ' Binary: 1000000000
End Enum

现在你可以将两个值组合起来得到一个新的值,并且可以区分这些值:

Dim testBits As NumberStyles
testBits = NumberStyles.AllowHexSpecifier _
        Or NumberStyles.AllowTrailingWhite _
        Or NumberStyles.AllowLeadingWhite       ' Binary: 1000000011

' If (1000000011 And 1000000000) <> 0 Then
If testBits.HasFlag(NumberStyles.AllowHexSpecifier) Then
    ' Do something
End If

如果有意义的话,您也可以将这些组合添加到枚举中:

<Flags()>
Enum NumberStyles
    ' ...
    Integer = 7                 ' Binary:        111
    Number = 111                ' Binary:    1101111
    Float = 167                 ' Binary:   10100111
    Currency = 383              ' Binary:  101111111
    HexNumber = 515             ' Binary: 1000000011
End Enum

关于你的例子

查看示例的二进制值。值 OneTwoFour 是 2 的幂,但 Three 不是。如果我扩展您的示例,也许您会看到问题:

<Flags()>
Enum BitWiseTest
    One = 1     ' Binary:    1
    Two = 2     ' Binary:   10
    Three = 3   ' Binary:   11
    Four = 4    ' Binary:  100
    Five = 5    ' Binary:  101
    Six = 6     ' Binary:  110
    Seven = 7   ' Binary:  111
End Enum

现在,做Six Or Three = Seven,这通常不是你想要的。当valueThreeSixSeven 时,value And Two 也是True,这也可能是你现在想要的。原因是Two 中设置的一位也存在于ThreeSixSeven 中,这取决于您选择值的方式。

【讨论】:

    【解决方案3】:

    它们不必是指数级的,没有语言限制。

    在大多数情况下,将它们定义为指数是有意义的,因此它们彼此独立。在非常少数情况下,您可能会受益于将指数 flag 值与预定义的 state 值相结合:

    public enum KitchenState{
        NothingHappening = 0,
    
        PanOnStove = 1,
        StoveOn = 2,
        Preheating = 3,
    
        EggsInPan = 4,
        EggsCooking = 7, 
    }
    

    在这种情况下,预热和 EggsCooking 是状态,PanOnStove、StoveOn 和 EggsInPan 是标志。这主要是一个噱头,但有时会派上用场

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-11-19
      • 1970-01-01
      • 2011-02-25
      • 2015-04-28
      • 2021-10-05
      • 2013-05-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多