Является ли хорошей практикой использование оператора xor для логических проверок? - PullRequest
147 голосов
/ 02 октября 2008

Мне лично нравится оператор exclusive или , ^, когда он имеет смысл в контексте логических проверок из-за его краткости. Я предпочитаю писать

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

чем

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

но меня часто смущают взгляды других опытных разработчиков Java (не только новичков), а иногда и комментарии о том, как его следует использовать только для побитовых операций.

Мне любопытно узнать, как лучше всего использовать оператор ^.

Ответы [ 13 ]

295 голосов
/ 02 октября 2008

Вы можете просто использовать != вместо.

27 голосов
/ 02 октября 2008

Я думаю, что вы ответили на свой вопрос - если вы получаете странные взгляды от людей, возможно, безопаснее использовать более явный вариант.

Если вам нужно это прокомментировать, то вам, вероятно, лучше заменить его более подробной версией и не заставлять людей задавать вопрос в первую очередь.

16 голосов
/ 02 октября 2008

Я считаю, что у меня много подобных разговоров. С одной стороны, у вас есть компактный, эффективный метод достижения вашей цели. С другой стороны, у вас есть кое-что, что остальная часть вашей команды может не понять, что затруднит его сохранение в будущем.

Мое общее правило - спрашивать, является ли используемая методика разумной для программистов. В этом случае я думаю, что разумно ожидать, что программисты будут знать, как использовать логические операторы, поэтому использование xor в операторе if - это нормально.

В качестве примера чего-то, что не было бы хорошо, возьмите хитрость использования xor для замены двух переменных без использования временной переменной. Это трюк, с которым я не ожидал бы, что все будут знакомы, поэтому он не прошел бы проверку кода.

14 голосов
/ 02 октября 2008

Я думаю, что было бы хорошо, если бы вы это прокомментировали, например, // ^ == XOR.

9 голосов
/ 22 февраля 2013

Вы всегда можете просто обернуть его в функцию, чтобы дать ему подробное имя:

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;

Вот вопрос Stackoverflow, связанный с заменой XOR .

6 голосов
/ 02 октября 2008

Я недавно использовал xor в проекте JavaScript на работе, и закончил тем, что добавил 7 строк комментариев , чтобы объяснить, что происходит. Основанием для использования xor в этом контексте было то, что один из терминов (term1 в приведенном ниже примере) может принимать не два, а три значения: undefined, true или false, тогда как другой (term2) ) может быть true или false. Мне пришлось бы добавить дополнительную проверку для undefined случаев, но с xor было достаточно следующего, поскольку xor заставляет первый член сначала быть оценен как логическое значение, позволяя undefined обрабатываться как false:

if (term1 ^ term2) { ...

В конце концов, это было немного излишним, но я все равно хотел оставить его там, как пасхальное яйцо.

5 голосов
/ 21 октября 2012

С учетом ясности кода мое мнение таково, что использование XOR в логических проверках не является типичным использованием для побитового оператора XOR. Из моего опыта побитовый XOR в Java обычно используется для реализации маски flag toggle поведения:

flags = flags ^ MASK;

Эта статья Випана Синглы объясняет случай использования более подробно.

Если вам нужно использовать побитовый XOR, как в вашем примере, прокомментируйте, почему вы его используете, так как вероятно, что даже побитовая грамотная аудитория остановится на своих треках, чтобы понять, почему вы его используете.

5 голосов
/ 10 апреля 2010
if((boolean1 && !boolean2) || (boolean2 && !boolean1)) 
{ 
  //do it 
} 

ИМХО этот код можно упростить:

if(boolean1 != boolean2) 
{ 
  //do it 
} 
0 голосов
/ 12 августа 2017

Я лично предпочитаю выражение "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;
}

Конечно, это решение влечет за собой использование якобы постороннего вызова функции, который сам по себе подлежит проверке Best Practices, но он избегает многословного (и безобразного) выражения "(boolean1 &&! Boolean2) || (boolean2 && ! boolean1) "!

0 голосов
/ 24 марта 2011

Как побитовый оператор, xor намного быстрее, чем любой другой способ его замены. Поэтому для критически важных и масштабируемых вычислений обязательным условием является xor.

Мое субъективное личное мнение: для любых целей абсолютно запрещено использовать равенство (== или! =) Для логических значений. Его использование показывает отсутствие базовой этики и основ программирования. Любой, кто смотрит на вас смущенным взглядом ^, должен быть отправлен обратно к основам булевой алгебры (мне хотелось написать «в реки веры» здесь :)).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...