在 Java 中创建“逻辑异或”运算符

Posted

技术标签:

【中文标题】在 Java 中创建“逻辑异或”运算符【英文标题】:Creating a "logical exclusive or" operator in Java 【发布时间】:2010-10-18 02:52:13 【问题描述】:

观察:

Java 有一个逻辑 AND 运算符。 Java 有一个逻辑 OR 运算符。 Java 有一个逻辑 NOT 运算符。

问题:

Java 没有逻辑 XOR 运算符 according to sun。我想定义一个。

方法定义:

作为一个方法,简单定义如下:

public static boolean logicalXOR(boolean x, boolean y) 
    return ( ( x || y ) && ! ( x && y ) );

方法调用:

该方法的调用方式如下:

boolean myVal = logicalXOR(x, y);

运算符用法:

我更希望有一个运算符,用法如下:

boolean myVal = x ^^ y;

问题:

我找不到任何关于如何在 Java 中定义新运算符的信息。我应该从哪里开始?

【问题讨论】:

什么?您提供的链接内容为“按位异或” 您是否想知道是否可以像在 C++ 中一样在 Java 中定义运算符? 看来你误解了&和&&的区别。两者都是逻辑运算符(在布尔值上)。 Starblue 的回答涵盖的范围更广。 仅仅因为它不在教程中,并不意味着Java没有它 - 教程并不(总是)完整。见Java Language Specification 15.22.2 它叫!=,还有一个逻辑异或叫== 【参考方案1】:

这是因为运算符重载是他们特意从语言中遗漏的东西。他们用字符串连接“欺骗”了一点,但除此之外,这样的功能不存在。

(免责声明:我没有使用过 java 的最后两个主要版本,所以如果它现在发布,我会感到非常惊讶)

【讨论】:

请记住,您也不能在 C++ 中定义新的运算符。你所能做的就是给旧的赋予新的意义。【参考方案2】:

Java确实有一个逻辑异或运算符,它是^(如a ^ b)。

除此之外,您不能在 Java 中定义新的运算符。

编辑:这是一个例子:

public static void main(String[] args) 
    boolean[] all =  false, true ;
    for (boolean a : all) 
        for (boolean b: all) 
            boolean c = a ^ b;
            System.out.println(a + " ^ " + b + " = " + c);
        
    

输出:

假 ^ 假 = 假 假 ^ 真 = 真 真 ^ 假 = 真 真 ^ 真 = 假

【讨论】:

当我写我的帖子时,这也逃过了我的记忆,但我认为你可以使用 ^ 作为逻辑运算符(以及按位)。 ^ 不仅是位运算符。它也是一个逻辑运算符。 ^ 运算符已重载。它对整数类型或布尔类型进行操作。 +1 以获得很好的答案 javashlook。 Eddie,它没有比 JLS 第 15.22.2 节“布尔逻辑运算符 &、^ 和 |”更明确。 当然,答案是 && 和 ||将跳过计算表达式的第二部分和 & 和 |将始终评估表达式的两个部分(来自我对 JLS 的阅读)。根据定义,^^ 总是必须评估这两个部分,因此其行为与 ^ 相同。大概是为什么没有^^ @Eddie:那和 ^^ 看起来太像表情了。 也许这是一个语义问题,但是当涉及到 XOR 时,按位和逻辑会产生相同的结果。因此,不需要不同的运算符。 XOR 运算符的简化真值表是 X ^ !X = 1。您不能在 XOR 中短路输入,因为您必须确定输入是否不同。如果您知道实际 XOR 门的制作方​​法,则更容易理解。【参考方案3】:

不是 x != y 吗?

【讨论】:

如果 x 和 y 是布尔值,那么 xor 和 != 的逻辑表是相同的: t,t => f ; t,f => t; f,t => t; f,f => f 莫里斯:啊,你简直让我大吃一惊!我怎么从来没有注意到这一点? @Milhous 你是说a != b != c 行不通,但a ^ b ^ c 行吗?在这种情况下,you are wrong. 莫里斯,太棒了!当有很多事情要做时,我碰巧忘记了简单的事情:) 当双方都是包装类时,这个方法会内爆,new Boolean(true) != new Boolean(true) 给出true【参考方案4】:

Java 中唯一的运算符重载是字符串上的 + (JLS 15.18.1 String Concatenation Operator +)。

社区多年来一直一分为三,1/3 不想要,1/3 想要,1/3 不关心。

您可以使用 unicode 来创建符号的方法名称...所以如果您有想要使用的符号,您可以执行 myVal = x.$(y);其中 $ 是符号,而 x 不是原语...但这在某些编辑器中会很狡猾,并且会受到限制,因为您无法在原语上执行此操作。

【讨论】:

【参考方案5】:

Java 有一个逻辑 AND 运算符。 Java 有一个逻辑 OR 运算符。

错了。

Java 有

两个逻辑 AND 运算符:普通 AND 是 &,短路 AND 是 &&,和 两个逻辑或运算符:正常的 OR 是 |和短路或是||。

XOR 仅作为 ^ 存在,因为不可能进行短路评估。

【讨论】:

有趣的评论。有记录吗? 我认为 & 和 |不是短路的,因为它们是按位运算符。事实上,不可能将它们短路。 @Krzysztof Jabłoński 它们是数字的按位运算符,但这里我们讨论的是布尔表达式。 @user666412 是的,在 Java 语言规范中(还有什么地方?)。 如果它有 2 个 AND 运算符和 2 个 OR 运算符,那么语句“Java 有一个逻辑 AND 运算符”和“Java 有一个逻辑 OR 运算符”没有错。根据定义,如果你有 2 个,那么你也有 1 个。【参考方案6】:

也许你误解了&&&|||之间的区别 快捷运算符&&|| 的目的是第一个操作数的值可以确定结果,因此第二个操作数不需要计算。

如果第二个操作数会导致错误,这将特别有用。 例如

if (set == null || set.isEmpty())
// or
if (list != null && list.size() > 0)

但是,使用 XOR,您总是需要计算第二个操作数才能得到结果,因此唯一有意义的操作是 ^

【讨论】:

【参考方案7】:

您可以使用Xtend (Infix Operators and Operator Overloading) 重载运算符并在 Java 上“停留”

【讨论】:

请注意,Xtend 不允许您覆盖插入符号 ^;你必须使用bool_1.xor(bool_2)。奇怪的是,解析器甚至不允许您使用插入符号;对于布尔值,您必须使用 xor,对于整数必须使用 bitwiseXor。当然,您可以重载另一个运算符,但这会让人很困惑。【参考方案8】:

这里是java的var arg XOR方法...

public static boolean XOR(boolean... args) 
  boolean r = false;
  for (boolean b : args) 
    r = r ^ b;
  
  return r;

享受

【讨论】:

这感觉它会有一些非常奇怪的行为。例如。 XOR(true,true,true) 返回 true,这似乎不像您对名为 XOR 的方法所期望的那样。我的预期行为是它总是返回 false(这当然没有帮助)【参考方案9】:

你可以写(a!=b)

这与a ^ b 的工作方式相同。

【讨论】:

【参考方案10】:

由于布尔数据类型像整数一样存储,如果与布尔值一起使用,位运算符 ^ 的功能类似于 XOR 操作。

//©Mfpl - XOR_Test.java

    public class XOR_Test 
        public static void main (String args[]) 
            boolean a,b;

            a=false; b=false;
            System.out.println("a=false; b=false;  ->  " + (a^b));

            a=false; b=true;
            System.out.println("a=false; b=true;  ->  " + (a^b));

            a=true;  b=false;
            System.out.println("a=true;  b=false;  ->  " + (a^b));

            a=true; b=true;
            System.out.println("a=true; b=true;  ->  " + (a^b));

            /*  output of this program:
                    a=false; b=false;  ->  false
                    a=false; b=true;  ->  true
                    a=true;  b=false;  ->  true
                    a=true; b=true;  ->  false
            */
        
    

【讨论】:

【参考方案11】:

以下是您的代码:

public static boolean logicalXOR(boolean x, boolean y) 
    return ( ( x || y ) && ! ( x && y ) );

是多余的。

为什么不写:

public static boolean logicalXOR(boolean x, boolean y) 
    return x != y;

?

另外,作为 javashlook said,已经有 ^ 运算符。

!=^ 对于布尔操作数(您的情况)的工作方式相同*,但对于整数操作数则不同。

* 备注: 1. 它们对于boolean(原始类型)的工作方式相同,但对于Boolean(对象类型)操作数不同。正如Boolean(对象类型)值可以具有值null。当!= 的一个或两个操作数为null 时,!= 将返回falsetrue,而在这种情况下^ 将抛出NullPointerException。 2.虽然它们的工作方式相同,但它们的优先级不同,例如与& 一起使用时:a & b != c & d 将被视为a & (b != c) & d,而a & b ^ c & d 将被视为(a & b) ^ (c & d)(题外话:哎呀,C 样式的优先级表很烂)。

【讨论】:

布尔值我喜欢!= @GKalnytskyi for Boolean!= 工作不正确。对于boolean 值,没关系。 != 和 ^ 对于布尔操作数完全相同工作。由于优先级不同,“false & false != true”与“false & false ^ true”会得到不同的结果。 @AlbertHendriks,我最好说它们工作相同,但有不同的优先级(尽管这只是术语问题)。 【参考方案12】:

这是一个例子:

给定 2 个 int 值,如果一个是负数,一个是正数,则返回 true。除非参数“negative”为真,否则只有当两者都为负时才返回真。

    public boolean posNeg(int a, int b, boolean negative) 
      if(!negative)
        return (a>0 && b<0)^(b>0 && a<0);
      
      else return (a<0 && b<0);
    

【讨论】:

【参考方案13】:

你所要求的没有多大意义。除非我不正确,否则您建议您要使用 XOR 以与 AND 和 OR 相同的方式执行逻辑运算。您提供的代码实际上显示了我所指的内容:

public static boolean logicalXOR(boolean x, boolean y) 
    return ( ( x || y ) && ! ( x && y ) );

您的函数具有布尔输入,当对布尔值使用按位异或时,结果与您提供的代码相同。换句话说,在比较单个位(布尔值)或比较较大值中的单个位时,按位异或已经很有效。把它放到上下文中,就二进制值而言,任何非零值都是 TRUE,只有 ZERO 是 false。

因此,要以与应用逻辑 AND 相同的方式应用 XOR,您要么只使用只有一位的二进制值(给出相同的结果和效率),要么必须将二进制值作为一个整体来评估,而不是每比特。换句话说,表达式 (010 ^^ 110) = FALSE 而不是 (010 ^^ 110) = 100。这将从操作中删除大部分语义含义,并表示您无论如何都不应该使用的逻辑测试。

【讨论】:

【参考方案14】:

A 和 B 必须是布尔值才能使 != 与 xor 相同,以便真值表看起来相同。您也可以使用 !(A==B) 大声笑。

【讨论】:

【参考方案15】:

我正在使用非常流行的类“org.apache.commons.lang.BooleanUtils”

这种方法已经过很多用户的测试并且安全。玩得开心。 用法:

boolean result =BooleanUtils.xor(new boolean[]true,false);

【讨论】:

最佳答案。谢谢!【参考方案16】:

您需要切换到 Scala 来实现自己的运算符

pipe example

【讨论】:

【参考方案17】:

Java 中的逻辑异或称为!=。如果你想迷惑你的朋友,你也可以使用^

【讨论】:

【参考方案18】:

这是一个使用 XOR(^) 的例子,来自 answer

byte[] array_1 = new byte[]  1, 0, 1, 0, 1, 1 ;
byte[] array_2 = new byte[]  1, 0, 0, 1, 0, 1 ;

byte[] array_3 = new byte[6];

int i = 0;
for (byte b : array_1)
    array_3[i] = b ^ array_2[i++];

输出

0 0 1 1 1 0

【讨论】:

【参考方案19】:

可以在java 8及以上使用流API实现

public static boolean logicalXOR(boolean x, boolean y)   // can modify to take [] or list of bools
    return Stream.of(x, y)  // modify as per method params
        .filter(bool -> bool)
        .count() == 1;

【讨论】:

以上是关于在 Java 中创建“逻辑异或”运算符的主要内容,如果未能解决你的问题,请参考以下文章

java之逻辑运算符

java逻辑运算符     真值表

Java 逻辑运算符与短路逻辑运算符

JAVA笔记03日

20190512 Java学习02

逻辑运算符