比较位和时按位与有什么影响?

What effect does a bitwise AND have when comparing bit sums?

我有一个使用位和来确定分支的决策树。

例如: 如果我们有规则:1,2,4,8,16 总和由以下因素确定:如果为真,则总和 += ruleId.

分支函数,而不是做:

if(sum == 23) =>
else if(sum == 15) =>

使用按位与:

if(sum & 23 == 23) =>
else if(sum & 15 == 15) =>

使用按位与和 == 有什么区别?

我需要做的是生成一个 List<Tuple<int,boo>> 来引导给定结果评估为真。我的想法是: 对于 23,例如:

1 && 2 && 4 && 8 && !16

将使它的计算结果为真。但是,按位AND对此有什么影响呢?我需要更改什么才能正确输出使其为真的表达式?

仅当总和等于您要测试的值时,相等运算符才会为真。按位 && 检查将确保由该数字表示的所有位都设置在您的值中。

例如

sum = 23 (10111),则 sum == 23 为真,sum & 23 == 23 也为真。

sum = 25 (11001),那么 sum == 23 会是 false,但是 sum & 23 现在 returns 17.

  11001
& 10111
 ======
  10001 (17)

What is the difference between using the bitwise AND and the == ?

==检查两个值是否相等,简单。按位与计算位匹配的值。当这与等于检查结合使用时,您实际上是在检查 sum 是否设置了与 23 使用的相同的位。

如果你把位写下来更容易理解,假设 sum = 31:

  0001 1111 // (sum 31)
& 0001 0111 // (23)
= 0001 0111 // (only set 1 if *both* are 1)

请注意,您最终得到的结果与 23 相同,因此当您执行 (sum & 23) == 23 时,您会得到 true。这样做的目的是检查是否设置了特定位。在 23 的情况下,您正在检查是否设置了位 16、4、2 和 1。

如果您想了解更多信息,

"C# Bit Flags" 是一个有用的搜索词。

请注意,您需要 在按位 AND 周围使用括号,因为优先顺序将首先尝试评估 ==

if((sum & 23) == 23)

这纯粹是在猜测您可能想要实现的目标,但如果您正在尝试执行已设置的每条规则,那么您可能需要这样的结果:

if((sum & 1) == 1)
    ExecuteRule1();
if((sum & 2) == 2)
    ExecuteRule2();
if((sum & 4) == 4)
    ExecuteRule4();
if((sum & 8) == 8)
    ExecuteRule8();
if((sum & 16) == 16)
    ExecuteRule16();

使用此代码,在 sum = 23 的情况下,它将执行规则 1、2、4 和 16。但会跳过规则 8。

当您选择了多个位时,您需要进一步比较(如==)。于是

if (sum & 020)

恰好选择一位。开启或关闭。

if (sum & 017)

选择最后四位,但如果设置了这些位中的任何一位,则计算结果为真。

if ((sum & 017) == 017)

选择最后四位,必须设置所有位才能使表达式为真。

但是,none 这些测试会查看可能设置的其他位。如果您想断言某些位已设置而其他位未设置,您会得到更复杂的测试:

if ((sum & 017) == 017 && !(sum & 060))

在某些时候,您越过了一个比位掩码更清楚地表达您进行相等比较的意图的地方。

顺便说一句,您会注意到我使用的是八进制常量。 对于位掩码 (IMO),八进制或十进制更易于使用和维护。

为什么要使用位运算?在您提到的特定情况下,这无关紧要(只要您将 AND 包裹在像 提及的括号中)。

但是,如果有些地方略有不同怎么办?例如,如果一个新的开发人员后来出现并且必须添加一个案例,并且不了解它是如何工作的。他们添加下一位(32 或 100000)并将他们的支票添加到 ifbottom

if((sum & 23) == 23) =>
else if((sum & 15) == 15) =>
//...
else if((sum & 31) == 31) =>

会发生什么?

嗯,二进制 31 &(按位与)二进制 23:

11111
10111
-----
10111

呃哦!评估为真!由于他们不知道更好,将其添加到底部,因此 23 首先评估为 TRUE,而 31 永远不会评估。

所以,这就变成了你的意图的问题。如果这是预期的行为(我对此表示怀疑),那么您可以使用按位操作,并且您将始终知道如果您正在检查,例如,23,您正在检查那些特定的位是否已设置,而不是它们是唯一的位集。如果您想知道是否仅设置了 23 中的所有位,请使用 (sum == 23)。