Создание «логического исключающего или» оператора в Java

274

Замечания:

У Java есть логический оператор AND.
У Java есть логический оператор ИЛИ.
У Java есть логический оператор НЕ.

Проблема:

Java не имеет никакого логического оператора XOR, в соответствии с солнцем . Я хотел бы определить один.

Определение метода:

Как метод он просто определяется следующим образом:

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


Вызов метода:

Этот метод вызывается следующим образом:

boolean myVal = logicalXOR(x, y);


Использование оператора:

Я бы предпочел иметь оператора, используемого следующим образом:

boolean myVal = x ^^ y;


Вопрос:

Я не могу найти ничего о том, как определить новый оператор в Java. С чего мне начать?

eleven81
источник
1
что? ссылка, которую вы дали, имеет содержание «побитовое исключающее ИЛИ»
Мэтью П. Джонс,
Вам было интересно, если бы вы могли определить операторы в Java, как вы можете в C ++?
avgvstvs
1
Кажется, вы неправильно поняли разницу между & и &&. Оба являются логическими операторами (на логическом). Ответ Starblue охватывает его более широко.
Власек
просто то, что его нет в учебнике , не означает, что в Java его нет - учебники не (всегда) завершены. См. Спецификацию языка Java 15.22.2
user85421
5
Это называется !=, есть также логический XNOR под названием==
Марк К Коуэн

Ответы:

695

У Java действительно есть логический оператор XOR , это ^ (как в 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);
        }
    }
}

Вывод:

ложь ^ ложь = ложь
ложь ^ правда = правда
правда ^ ложь = правда
правда ^ правда = ложь
javashlook
источник
5
Это также ускользнуло от моей памяти, когда я написал свой пост, но я думаю, что вы МОЖЕТЕ использовать ^ как логический оператор (а также побитовый).
Нил Коффи
144
^ не только побитовый оператор. Это также логический оператор. Оператор ^ перегружен. Он работает на целочисленных типах или логических типах. +1 за отличный ответ javashlook. Эдди, это не становится более явным, чем раздел 15.22.2 JLS, «Булевы логические операторы &, ^ и |».
erickson
97
И, конечно же, ответ таков: && и || пропустит оценку 2-й части выражения и & и | всегда будет оценивать обе части выражения (из моего чтения JLS). ^^ всегда должен оценивать обе части по определению, поэтому ведет себя идентично ^. Вероятно, почему нет ^^
Эдди
81
@Eddie: Это и ^^ слишком похоже на смайлик.
Майкл Майерс
5
Может быть, это вопрос семантики, но когда дело доходит до XOR, побитовое и логическое дают одинаковый результат. Следовательно, нет необходимости в разных операторах. Упрощенная таблица истинности для оператора XOR: X ^! X = 1. Вы не можете закорачивать вход в XOR, потому что вы должны определить, являются ли входы различными. Намного легче понять, если вы знаете, как изготовлены настоящие ворота XOR.
hfontanez
305

Разве это не х! = У?

Морис Перри
источник
5
Если x и y являются логическими значениями, то логическая таблица для xor и! = Идентична: t, t => f; t, f => t; f, t => t; f, f => f
Грег Кейс
81
Морис: Arrgh ты просто взорвал мой разум! Как я никогда этого не замечал?
8
@ Milhous Вы говорите a != b != c, не будет работать, но a ^ b ^ cбудет? В этом случае вы не правы .
fredoverflow
3
Морис, просто великолепно! Мне случается терять простые вещи из поля зрения, когда есть чем заняться :)
sberezin
6
Это Approch взрывается , когда обе стороны обертки классов, new Boolean(true) != new Boolean(true)дает true.
Властимил Овчачик
74

У Java есть логический оператор AND.
У Java есть логический оператор ИЛИ.

Неправильно.

Ява имеет

  • два логических оператора «И»: нормальное «И» - это «И» и короткое замыкание «И» - «&&», а также
  • два логических оператора ИЛИ: нормальное ИЛИ есть | И короткое замыкание ИЛИ ||

XOR существует только как ^, потому что оценка короткого замыкания невозможна.

starblue
источник
2
Интересный комментарий. Это задокументировано?
user666412
1
Я думаю, и и | не являются короткими замыканиями, потому что они являются побитовыми операторами. И на самом деле их невозможно замкнуть.
Кшиштоф Яблонский
3
@Krzysztof Jabłoński Они являются побитовыми операторами чисел, но здесь мы говорим о булевых выражениях.
звездный синий
3
@ user666412 Да, в спецификации языка Java (где еще?).
августа
18
Если он имеет 2 оператора AND и 2 оператора OR, то операторы «Java имеет логический оператор AND» и «Java имеет логический оператор OR» не ошибочны. По определению, если у вас есть 2 чего-то, то у вас также есть 1 из этого.
RyanfaeScotland
31

Возможно, вы неправильно поняли разницу между &и &&, |и || Цель операторов быстрого вызова &&и ||заключается в том, что значение первого операнда может определять результат, и поэтому второй операнд не нужно оценивать.

Это особенно полезно, если второй операнд приведет к ошибке. например

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

Однако с XOR вам всегда нужно вычислять второй операнд, чтобы получить результат, поэтому единственной значимой операцией является ^.

Питер Лори
источник
20

Вы можете просто написать (a!=b)

Это будет работать так же, как и a ^ b.

Shuliyey
источник
9

Это связано с тем, что перегрузка операторов - это то, что они специально не учитывают в языке. Они немного «обманывают» при конкатенации строк, но кроме этого, такой функциональности не существует.

(отказ от ответственности: я не работал с двумя последними основными выпусками Java, поэтому, если он появится сейчас, я буду очень удивлен)

Кевин Андерсон
источник
5
Имейте в виду, что вы не можете определить новые операторы в C ++. Все, что вы можете сделать, это дать новое значение старым.
Дэвид Торнли
7

Единственная перегрузка оператора в Java - это + для строк ( JLS 15.18.1 Оператор конкатенации строк + ).

Сообщество делится на 3 года, 1/3 не хочет, 1/3 хочет, а 1/3 не волнует.

Вы можете использовать юникод для создания имен методов, которые являются символами ... поэтому, если у вас есть символ, который вы хотите использовать, вы можете сделать myVal = x. $ (Y); где $ - символ, а x - не примитив ... но в некоторых редакторах это будет хитроумно и ограниченно, поскольку вы не можете сделать это на примитиве.

TofuBeer
источник
7

Следующий ваш код:

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 , уже есть ^оператор.

!=и ^работают одинаково * для булевых операндов (ваш случай), но по-разному для целочисленных операндов.

* Примечания:
1. Они работают одинаково для boolean(примитивного типа), но не Boolean(для типа объекта) операндов. Как Boolean(тип объекта) значения могут иметь значение null. И !=вернется falseили trueкогда один или оба его операнда есть null, пока ^бросит NullPointerExceptionв этом случае.
2. Хотя они работают одинаково, они имеют различный приоритет, например, при использовании с &: a & b != c & dбудет обрабатываться как a & (b != c) & d, а a & b ^ c & dбудет обрабатываться как (a & b) ^ (c & d)(offtopic: ой, таблица приоритетов в стиле C отстой).

Саша
источник
1
Для булевых значений мне нравится!=
Г.Кальницкий
1
@GKalnytskyi для Booleanзначений !=работает неправильно. Для booleanценностей это нормально.
vadipp
2
! = и ^ не работают одинаково для булевых операндов. Вы получите разные результаты для «false & false! = True» и «false & false ^ true» из-за приоритета.
Альберт Хендрикс
1
@ AlbertHendriks, я бы лучше сказал, что они работают одинаково, но имеют разный приоритет (хотя это просто вопрос терминологии).
Саша
6

Вот XAR-метод var arg для Java ...

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 (что, конечно, не полезно)
Ричард Тингл
5

Логический эксклюзив - или на Java называется !=. Вы также можете использовать, ^если хотите запутать своих друзей.

Doradus
источник
2

Вы можете использовать Xtend (Infix Operators и Operator Overloading), чтобы перегрузить операторы и «остаться» на Java

иммуноглобулин А
источник
Обратите внимание, что Xtend не позволяет вам переопределить курсор ^; Вы должны использовать bool_1.xor(bool_2). Как ни странно, парсер даже не позволяет вам использовать каретку; Вы должны использовать xorдля логических и bitwiseXorцелых чисел. Конечно, вы могли бы перегружать другого оператора, но это могло бы привести в замешательство.
Кельвин
2

То, что вы просите, не имеет большого смысла. Если я не ошибаюсь, вы предлагаете использовать XOR для выполнения логических операций так же, как AND и OR. Ваш код на самом деле показывает, что я ссылаюсь на:

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

Ваша функция имеет логические входы, и при использовании побитового XOR для логических значений результат будет таким же, как и код, который вы предоставили. Другими словами, побитовый XOR уже эффективен при сравнении отдельных битов (логических значений) или при сравнении отдельных битов в больших значениях. Чтобы поместить это в контекст, в терминах двоичных значений любое ненулевое значение равно TRUE, и только ZERO - false.

Таким образом, для применения XOR таким же образом, как применяется логическое И, вы должны либо использовать только двоичные значения только с одним битом (давая тот же результат и эффективность), либо двоичное значение должно оцениваться как целое, а не на бит. Другими словами, выражение (010 ^^ 110) = FALSE вместо (010 ^^ 110) = 100. Это удалит большую часть семантического значения из операции и будет представлять собой логический тест, который вы все равно не должны использовать.

user2904660
источник
1

A и B должны быть логическими значениями, чтобы сделать! = Такими же, как xor, чтобы таблица истинности выглядела одинаково. Вы также можете использовать! (A == B) LOL.

Джон Тейберт
источник
1

Я использую очень популярный класс "org.apache.commons.lang.BooleanUtils"

Этот метод проверен многими пользователями и безопасен. Радоваться, веселиться. Использование:

boolean result =BooleanUtils.xor(new boolean[]{true,false});
Adam111p
источник
0

Поскольку логический тип данных хранится как целое число, битовый оператор ^ функционирует как операция 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
            */
        }
    }
LEDON
источник
0

Вот пример:

Если задано 2 значения типа int, вернуть true, если один отрицательный, а другой положительный За исключением случаев, когда параметр «отрицательный» имеет значение «истина», возвращает значение «истина», только если оба значения являются отрицательными.

    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);
    }
Шадман Судипто
источник