Hung-Yi's LogoHung-Yi’s Journal

Where's My Logical XOR Operator?

Learn a simple trick to mimic XOR and XNOR boolean operators in your favorite language where it might be missing.

Many popular programming languages don’t have logical XOR or XNOR operators. 1 Because of this, it may not be clear how to check scenarios such as:

  1. Either one of A or B hold true, but not both.
  2. Either both A and B hold true, or are both false, but not either one of them individually.

In case you’re unfamiliar with boolean logic, note that those scenarios are equivalent to:

  1. A XOR B
  2. A XNOR B

Without XOR or XNOR, you may be tempted to write code this way:

// A XOR B
(A || B) && !(A && B)

// A XNOR B
(!A && !B) || (A && B)

…which could work, with lots of head scratching and unit testing…

Until you realize that it can be simplified greatly into:

// A XOR B
A !== B

// A XNOR B
A === B

Super elegant, isn’t it? 🪄

How does this trick work?

Observe that we’re checking equality between boolean2 values, so the truth tables look something like this:

// XOR
false !== false // => false
false !== true  // => true
true !== false  // => true
true !== true   // => false

// XNOR
false === false // => true
false === true  // => false
true === false  // => false
true === true   // => true

The key insight is that if the two conditions are different, then one and only one of them must be true, which gives you the XOR condition. Inverting it trivially gives you XNOR.

Is it useful?

Admittedly, it’s probably not that useful in everyday programming. It’s very rare to have to check for a XOR condition in real life (it might even be a code smell). I would have come up with a fun Christmas example if I could think of one, but I really couldn’t.

Hey now — at least you can do part 2 of day 2 of Advent of Code 2020 without having to write a bunch of boolean spaghetti ✌

Footnotes:

1

Your favorite programming language may have bitwise XOR or XNOR operators though, but they’re not directly useful for checking conditionals, since they work on bits (i.e. 1s and 0s) instead of boolean values (i.e. true and false).

2

And they must be boolean values, otherwise it may break. In JavaScript and TypeScript, you can force values to be boolean using ! and !!.