在比较位总和时,按位AND有什么影响?

时间:2016-02-01 16:54:13

标签: c# bitwise-operators

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

例如: 如果我们有规则:1,2,4,8,16 总和由下式确定:如果为真则为sum + = ruleId。

分支功能,而不是:

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

使用按位AND:

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

使用按位AND和==?

之间有什么区别

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

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

会使其评估为真。但是,按位AND会对此产生什么影响?我需要更改哪些内容才能正确输出会使其成为真的表达式?

4 个答案:

答案 0 :(得分:3)

  

使用按位AND和==?

之间有什么区别

==检查这两个值是否相等,简单。按位AND计算位匹配的值。当这与equals检查结合使用时,您有效地检查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和。

如果您想了解更多信息,

"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.

答案 1 :(得分:2)

为什么要使用按位操作?在你提到的特定情况下,它不重要(只要你将AND包括在像musefan提到的那些parens中)。

但是,如果某些事情略有不同会发生什么?例如,如果新开发人员稍后出现并且必须添加案例,并且不了解其工作原理。他们添加下一位(32或100000)并将其检查添加到if底部

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

会发生什么?

好吧,31二进制&amp; (按位AND)23二进制:

11111
10111
-----
10111
哦,哦!评估为真!而且,由于他们不知道更好,将其添加到底部,23首先评估为TRUE,而从未评估31。

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

答案 2 :(得分:0)

只有当总和等于您要测试的值时,等于运算符才会成立。按位&amp;&amp; check将确保该值所代表的所有位都设置在您的值中。

例如

sum = 23(10111),则sum == 23将为真,sum&amp; 23 == 23。

sum = 25(11001),则sum == 23将为false,但sum&amp; 23现在返回17。

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

答案 3 :(得分:0)

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

if (sum & 020)

精确选择一位。无论是打开还是关闭。

if (sum & 017)

选择最后四位,但如果设置了这些位,则评估为真。

if ((sum & 017) == 017)

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

但是,这些测试都没有查看可能设置的其他位。如果你想断言某些位被设置而其他位不被置位,那么你会得到更复杂的测试:

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

在某些时候,你会越过那里更清楚地表达你进行相等比较的意图而不是位掩码。

顺便说一句,你会注意到我正在使用八进制常量。 八位或十进制更容易使用和维护位掩码(IMO)。