Friday, April 25, 2008

XOR vs Equality Operators (^ vs !=)

A while ago, I committed code to my client's code-base that reads like this:

public boolean isSomethingValid() {
  return !a ^ b;
}

At the end of the day, Nick Malnick came to me and mentioned that a discussion broke out in his room because "someone used an XOR!" I went to the room to see what the matter was, and apparently another programmer who encountered that statement rushed to others for help because he didn't know what to make of the ^ operator and didn't know it was even a part of the Java syntax.

As Nick and I were leaving home, we had a talk about it, and I realized that I could have achieved exactly the same effect by writing the following instead:

public boolean isSomethingValid() {
  return a == b;
}

In fact, we discovered the following equivalence relationships:

 a ^ b <=> a != b
!a ^ b <=> a == b

Given these relationships, we had further discussion about whether it's a good idea at all to use the XOR operator in our client's code-base given that the developers rarely ever use it and aren't accustomed to it.

So, again in the spirit of the past blog post If-Else vs Direct Return and Manuel's blog post If Then (If Then Else) Else (If Then Else), I'd like to know the public's opinion on the matter.

Would you use XOR or equality operators? Does the decision possibly depend on the context? In other words, do the equality operators make more sense in some situations and XOR make more sense in others? If so, what are the different situations that warrant the use of each?

6 comments:

Dave Hoover said...

Andy, can you explain your motivation for using it in this specific situation? What made you choose XOR rather than ==?

Annas "Andy" Maleh said...

In my case, a and b were not related to each other conceptually. They were two different conditions that needed to be checked to determine the method return value (e.g. !SUBMITTED.equals(status) ^ GUEST.equals(customerRole)), so it didn't seem to make sense conceptually to say a==b.

The method had to evaluate to true when:
a = true , b = true
a = false, b = false

This represents the NXOR operation, which is written in Java as !(a ^ b) or !a ^ b

Chris Recoskie said...

IMHO, anything that makes someone reading your code have to scratch their head and think about what you were trying to do is a bad thing.

Unless you really needed speed in this method, I'd think an if-then-else would be the way to go. Way more readable.

If you really need the speed of XOR, then comment the code profusely so people know what the heck you are doing and why.

Sadly, few people program in assembly much these days (where XOR was a great way to do equality tests), nor does the average developer work on cryptography (where XOR is used to apply one time pads and the like), dor do they tend to write low level graphics code (draw something in XOR quickly for a temporary effect like rubber band selection, draw it there again to cheaply reset the graphics back to what they were). The net effect of this is that most developers probably don't even know what XOR is.

casey said...

I didn't know Java had a logical XOR operator, that's pretty neat. Sounds like you had a good conceptual reason for using it, and there's nothing wrong with expanding your clients' minds a bit!

Andrew Niefer said...

I have used XORs more than once. A quick search reveals 6 in code I wrote in the CDT parser.

I expect their use was a reflection of the logic in my head at the time. Even though they may be equivalent in the binary case, I would say they imply a different thought process in the context of a larger algorithm, which in some cases might make them easier to understand than using !=. (Assuming of course the reader knows what XOR is :)).

Don't discard the ^ completely, at the very least, there is still the bitwise version.

Ed Merks said...

It seems to me that ^ should be used only when you're doing bit masking not when you are working with boolean logic. Although all the bitwise operators apply for booleans by interpreting false and true to be represented by zero and one, it doesn't seem like a very intuitive way of expressing boolean logic.