使用xor运算符进行布尔检查是否是好习惯?[关闭]


150

由于布尔值的简洁性,我个人喜欢布尔运算符中的Exclusive^,,运算符。我更喜欢写

if (boolean1 ^ boolean2)
{
  //do it
}

if((boolean1 && !boolean2) || (boolean2 && !boolean1))
{
  //do it
}

但是我经常会从其他经验丰富的Java开发人员(不仅是新手)中获得困惑的外观,有时还会评论如何仅将其用于按位运算。

我对有关使用^操作员的最佳做法感到好奇。

Answers:


298

您可以简单地使用!=


36
bool1 ^ bool2 ^ bool3比我更合乎逻辑的bool1 != bool2 != bool3
想法是–

4
我的脑袋疼。那么!=会产生不正确的结果吗?
vemv 2011年

27
@vemv !=产生booleans的正确结果(但不包含Booleans,因此要小心)。它并不总是很漂亮,例如, (some != null) != (other != null)可读性不高。您要么用显式布尔值提取零件,要么!=用单独的方法提取。
ivant

23
原因如下:a ^ b=>“ a或b,但不能同时包含两者”,a != b=>“ a不等于b”。(@RobertGrant说了什么)。如果大多数人知道xor是什么,则他们会更容易理解第一个(如果您在计算领域,这非常有用...)
Harold R. Eason

2
@ HaroldR.Eason在这里很挑剔:a != b=>“ a对b并不相同”
Mario Reutter

27

我认为您已经回答了自己的问题-如果您得到别人的怪异表情,那么使用更明确的选项可能更安全。

如果您需要对其进行评论,那么最好将其替换为更详细的版本,而不要让人们首先问这个问题。


6
我可以断言您,当您认真地编写(boolean1 && !boolean2) || (boolean2 && !boolean1)现实生活中的应用程序代码时,您会从我这里得到奇怪的表情……
Holger

17

我发现我有很多类似的对话。一方面,您有一种紧凑,有效的方法来实现自己的目标。另一方面,您的团队其他成员可能不了解某些内容,因此将来很难维护。

我的一般规则是询问所使用的技术是否可以使一般程序员知道。在这种情况下,我认为期望程序员知道如何使用布尔运算符是合理的,因此在if语句中使用xor是可以的。

作为某些事情的例子,请使用技巧,即使用xor交换两个变量而不使用临时变量。我不希望每个人都熟悉这种技巧,因此不会通过代码审查。


14

我认为,如果您发表评论的话就可以了// ^ == XOR


10

您总是可以将其包装在一个函数中以为其指定详细名称:

public static boolean XOR(boolean A, boolean B) {
    return A ^ B;
}

但是,在我看来,对于不知道^运算符对Google有用的人来说,这并不难,这确实非常快捷。第一次之后就不会很难记住。由于您要求其他用途,因此通常使用XOR进行位屏蔽。

您也可以使用XOR交换两个变量中的值,而无需使用第三个临时变量

// Swap the values in A and B
A ^= B;
B ^= A;
A ^= B;

这是一个与XOR交换有关Stackoverflow问题


6

我最近在工作的JavaScript项目中使用了xor,最后添加了7行注释来解释发生了什么。在这种情况下使用异或的理由是,术语(中的一个term1在下面的示例)可以采取不是两个而是三个值:undefinedtruefalse而另一个(term2)可以是truefalse。我将不得不为这种undefined情况添加一个额外的检查,但是使用xor,以下内容就足够了,因为xor会强制第一个条件首先被评估为布尔值,undefined因此将其视为false

if (term1 ^ term2) { ...

最后,这有点过分了,但是我还是想把它保留在那里,就像是个复活节彩蛋。


恕我直言,在不常见的情况下,不依赖于隐式转换,最好将转换设为显式。一般来说,“让未定义的内容被当作假”是任何语言的可疑做法。我没有在Java中使用三态值,但是在C#中,bool? a可以使用显式测试值是否为真a == true-Java中是否有类似的技术?在C#中,给定两个bool?值,“将null处理为false”将导致(a == true) ^ (b == true)。等效公式为(a == true) != (b == true)。您可以在Java中做类似的事情吗?
制造商史蒂夫(Steve),

5
if((boolean1 && !boolean2) || (boolean2 && !boolean1)) 
{ 
  //do it 
} 

恕我直言,此代码可以简化:

if(boolean1 != boolean2) 
{ 
  //do it 
} 

5

考虑到代码的清晰性,我认为在布尔检查中使用XOR不是XOR按位运算符的典型用法。根据我的经验,Java中的按位XOR 通常用于实现掩码flag toggle行为:

flags = flags ^ MASK;

Vipan Singla的这篇文章更详细地解释了用例。

如果您需要在示例中使用按位异或,请说明使用它的原因,因为它甚至可能需要位有识字的听众停下来了解自己为什么使用它。


-1

由于其简洁性,我个人更喜欢“ boolean1 ^ boolean2”表达式。

如果我在您的情况下(以团队形式工作),则可以通过将“ boolean1 ^ boolean2”逻辑封装在具有描述性名称的函数(例如“ isDifferent(boolean1,boolean2)”)中来达成妥协。

例如,不使用“ boolean1 ^ boolean2”,而是这样调用“ isDifferent(boolean1,boolean2)”:

if (isDifferent(boolean1, boolean2))
{
  //do it
}

您的“ isDifferent(boolean1,boolean2)”函数如下所示:

private boolean isDifferent(boolean1, boolean2)
{
    return boolean1 ^ boolean2;
}

当然,此解决方案需要使用表面上无关的函数调用,该函数本身受最佳实践的审查,但避免了冗长(且难看)的表达式“(boolean1 &&!boolean2)||(boolean2 &&!boolean1) “!


-2

如果使用方式合理,为什么不呢?尽管您的团队无法立即认出操作员,但随着时间的推移他们会认出来。人类一直在学习新单词。为什么不在编程中?

我可能要指出的唯一警告是“ ^”不具有第二个布尔检查的短路语义。如果您确实需要短路语义,那么静态util方法也可以使用。

public static boolean xor(boolean a, boolean b) {
    return (a && !b) || (b && !a);
}

16
我认为xor不会发生任何短路-您必须同时知道a和b才能评估结果。
Thelema

7
同样,参数将在调用时进行评估,因此不会发生任何短路。
erikkallen 2009年

3
此外,xor应该是机器级别的单个操作。
食人魔赞美诗

您可能应该查找短路评估和惰性评估之间的差异。短路评估是一种代码样式,可防止调用否则会导致运行时错误,例如被零除。在C语言中,它可以是“ if(分母!= 0 &&分子/分母)”,它本身利用惰性计算来防止被零除。您的回答也纯粹是推测性的。
2013年

2
老实说,程序员编写的函数xor确实可以执行xor运算符的功能,但是以一种绕行方式进行操作,这在我的脑海中会提出比刚使用的程序员更多的问题(特别是关于能力)^
Stijn de Witt

-3

!=比较两个变量是可以的。但是,通过多个比较它不起作用。


-3

作为按位运算符,xor比任何其他替换方法快得多。因此,对于性能至关重要且可扩展的计算,xor势在必行。

我的主观个人意见:出于任何目的,绝对禁止对布尔值使用相等(==或!=)。使用它表明缺乏基本的编程道德和基本原理。任何对^感到困惑的人都应该回到布尔代数的基础上(我很想在这里写下“信仰之河” :))。


1
除了JIT非常擅长进行钥匙孔(小)优化外,例如将一个布尔表达式替换为另一个布尔表达式。
David Leppik

1
另外,^主要不是布尔(逻辑)运算符,而是按位运算符。它告诉读者放慢速度,因为可能存在符号错误。如果将^用作!=,则如果您使用C进行编程,将会非常混乱。按位运算符向您的读者(包括您在内调试代码的人)发出信号,使其放慢速度并查找符号错误。 。他们可能很棘手。例如,您知道Java的%不是像C或Python那样的真正模吗?我曾经有一段代码,它们在C,JavaScript和Python中运行相同,但在Java中却没有。
David Leppik

6
这是怎么被反对的?首先,在Java XOR和!=中被编译[ stackoverflow.com/a/4175512/202504](完全相同的代码),其次,即使在汇编程序测试相等性和xor时,每个都是简单的操作。您是否有任何数字可以支持您的陈述?
jmiserez

-4
str.contains("!=") ^ str.startsWith("not(")

对我来说比看起来更好

str.contains("!=") != str.startsWith("not(")
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.