16

First, some background: I am an IT teacher-in-training and I'm trying to introduce the boolean operators of java to my 10th grade class. My teacher-mentor looked over a worksheet I prepared and commented that I could let them use just a single & or | to denote the operators, because they "do the same thing".

I am aware of the difference between & and &&.
& is a bitwise operator intended for use between integers, to perform "bit-twiddling".
&& is a conditional operator intended for use between boolean values.

To prove the point that these operators do not always "do the same thing" I set out to find an example where using the bitwise between boolean values would lead to an error. I found this example

boolean bitwise;
boolean conditional;
int i=10, j=12;
bitwise = (i<j) | ((i=3) > 5); // value of i after oper: 3
System.out.println(bitwise+ " "+ i);
i=10; 
conditional = (i<j) || (i=3) > 5 ;  // value of i after oper: 10
System.out.println(conditional+ " "+ i);
i=10; 
bitwise = (i>j) & (i=3) > 5;   // value of i after oper: 3
System.out.println(bitwise+ " "+ i);
i=10; 
conditional = (i>j) && (i=3) > 5;  // value of i after oper: 10
System.out.println(conditional+ " "+ i);

This example shows that if a value has to be changed by the second half of the expression, this would lead to a difference between the results, since bitwise is an eager operator, while the conditional behaves as a short circuit (does not evaluate the second half, if the first half is false in the case of && and true in the case of ||).

I have an issue with this example. Why would you want to change a value at the same time as you do a comparision on it? It doesn't seem like a robust way to code. I've always been averse to doing multiple operations in a single line in my production code. It seems like something a "coding cowboy" with no conscience as to the maintainability of his code would do. I know that in some domains code needs to be as compact as possible, but surely this is a poor practice in general?

I can explain my choice of encouraging the use of && and || over & and | because this is an accepted coding convention in software engineering.

But could someone please give me a better, even real-world, example of using a bitwise operator in a conditional expression?

Deerasha
  • 165
  • 1
  • 1
  • 8

5 Answers5

16

it is appropriate when you are performing a masking operation

if ((a & b) > 0) { ... }

where a and b are integers

|| and | and && and & are not interchangable

| and & will amost never appear in a conditional expression by themselves (the point of the link you included is that such things are most often errors)

EDIT: Don't argue with your mentor; even if you win, you lose. Instead, explain that you don't want to confuse the students by mixing logical operators and bitwise operators in the same lesson. You could explain that if i=3 and j=2 then i&j = 2, while i&&j is an error. However, the simpler explanation is that you're teaching boolean (logical) operators, so throwing in special-case bitwise equivalents is a distraction from the main point of the lesson. There's no need to make the mentor "wrong", and no need to produce counter-examples. The focus of the lesson is on boolean operators, not bitwise operators.

As a corollary, when you start to teach bitwise operators, there's no need to show the special cases where + and - produce the same results as & and |

Steven A. Lowe
  • 33,808
  • 2
  • 84
  • 151
  • The code above isn't wrong though, it may be confusing but as it stands that code does not contain an error does it? I agree that using bitwise operators in this way is not very readable, I wouldn't like it if I saw it in a code review, but it is legal Java (and C# too, ignoring the System.out.println). – Steve Apr 14 '11 at 18:17
  • Thanks for answering @Steven A. Lowe. You said "|| and | and && and & are not interchangeable" but `bitwise = !(true & true == false);` and `condition = !(true && true == false);` will both evaluate to true, so in this case they are interchangeable? Syntactically perhaps, since the code still compiles. I would agree that they are used for different things semantically, as I mentioned in paragraph 2. You say that ! and & "almost never appear in a conditional by themselves". I am looking for these "almost never" cases, and wondering whether they do legitimately exist. – Deerasha Apr 14 '11 at 19:05
  • @Deerasha: || and && operate _only_ on booleans. & and | operate on integers _and_ booleans - there is little point in using bitwise operators (intended to operate on _multiple bits_) to manipulate booleans, and doing so with abandon can lead to confusing code and unexpected behaviors (i.e. if you accidentally use an integer instead of a boolean, the bitwise operators will not complain) – Steven A. Lowe Apr 14 '11 at 19:09
  • Yes @Steve Haigh, the compiler doesn’t reject it, but it isn’t the right way to use them, judging from the published coding standard I linked to. Can I comfortably rest on dismissing it because it does not comply with a coding standard, or should java maybe indicate that this is an improper use? – Deerasha Apr 14 '11 at 19:11
  • @Steven A. Lowe: You are right and this is why I am _against_ using the bitwise operators. My apologies if I had not made that clear. However I need to produce some evidence to this teacher-mentor as to why it is so undesirable. *I am looking for an example of one of these unexpected behaviours you mention.* The only example I found was the one above, and I think it isn’t suitable because of the reasons stated in paragraph 5. – Deerasha Apr 14 '11 at 19:23
  • @Deerasha: see edits – Steven A. Lowe Apr 14 '11 at 19:44
  • 2
    @Steven A. Lowe: _if i=3 and j=2 then i&j = 2, while i&&j is an error_ This is brilliant! It’s simple and it makes the point. At 10th grade level this is also a likely mistake to make, since they are still getting used to the Boolean type and what the operators would apply to. Thank you so much! Great advice on not arguing with my mentor either. – Deerasha Apr 14 '11 at 20:11
13

The non-bitwise operators && and || are short-circuit operators. In other words, with &&, if the LHS is false, the RHS will never be evaluated; with || if the LHS is true, then the RHS will never be evaluated. On the other hand, the bitwise operators & and | are non-short-circuit, and will always evaluate both the LHS and the RHS. Otherwise, they're equivalent in an if statement.

The only time I can see value in using the non-short-circuit operators is if the RHS has some kind of desirable side-effect that you want to happen in all cases. I can't think of a specific example where you would want this, and I don't believe it's good practice, but that's the difference.

Jonathan
  • 1,839
  • 2
  • 12
  • 11
  • 1
    +1. Exactly right, when comparing booleans bitwise and logical operators always return the same result, but (in Java and C# at least) only the logical operators short circuit. – Steve Apr 14 '11 at 18:14
  • Thank you for answering. Your paragraph 1 was what I was trying to get at in my paragraph 4, by stating that bitwise is an _eager operator_ while the conditional behaves as a _short circuit_. Your paragraph 2 is the concern I described in my paragraph 5. So I’m aware of the difference but I’m looking for that specific example neither you nor I can think of. – Deerasha Apr 14 '11 at 19:30
7

The general philosophical answer is that using bitwise operators for boolean operators is atypical and makes the code harder to read. In practice (for code that is in production), more readable code is easier to maintain and thus more desirable.

For a real-world use of the need for short-circuit operators, see cases such as:

if (args.length > 0 && args[0] == 'test') ....

if (b != NULL && b.some_function()) ...

if (b == NULL || b.some_function()) ...

These type of operations show up frequently in real-world code.

Ugo
  • 138
  • 5
Kathy Van Stone
  • 171
  • 1
  • 3
  • Tfa. How do I explain to my 15 yr olds that 1 `&` is “harder to read” than 2? I don’t have an example in which the 2 operators don’t work in the same way for Boolean operands. I agree on your point about more readable and easier to maintain code. I want to encourage them to write beautiful code. But having some proof in my bag of tools would be more convincing than “because I said so”. I do have it stated as a standard at that link, and may have to rely on that alone if I don’t get the example I’m looking for. As I asked @Steve Haigh: should java be indicating this as an improper use? – Deerasha Apr 14 '11 at 20:04
  • @Deerasha I was thinking more of an argument with your mentor. For the class don't even try to tell them that you can use bitwise operators for logical conditions. – Kathy Van Stone Apr 15 '11 at 18:40
5

You will use bitwise operators if you compare Bitmask enumerations. For example, you have an enumeration of states and an object that can be in more than one of those states. In this case, you'll do a bitwise or to assign more than one state to your object.

for example state = CONNECTED | IN_PROGRESS where CONNECTED could be 0x00000001 and IN_PROGRESS 0x00000010

For more info, look up flag enums documentation.

anthonyvd
  • 645
  • 4
  • 12
  • Thanks to you I’ve learned an application of bitwise operators I hadn’t know about before! But in this example, _only_ the bitwise operator applies. I’m looking for a piece of well-written code where using the bitwise rather than the conditional would lead to compilation, but an incorrect output. That is, if such a code snippet exists. – Deerasha Apr 14 '11 at 19:49
  • I don't think this can happen in Java as I believe calling the | or & operators on values that can't be bitwise and'd or or'd just performs a logical | or &. I can't recall if this is the case in Java, but know for sure it is in C# MSDN: ["Binary | operators are predefined for the integral types and bool. For integral types, | computes the bitwise OR of its operands. For bool operands, | computes the logical OR of its operands"](http://msdn.microsoft.com/en-us/library/kxszd0kx(v=vs.71).aspx) – anthonyvd Apr 14 '11 at 20:09
  • After some more research, I found out that [the only difference between | and || and & and && for boolean operands in Java is the short circuit behavior](http://www.sap-img.com/java/java-boolean-logical-operators.htm) so the scenario you're describing isn't really possible. – anthonyvd Apr 14 '11 at 20:12
0

a simpler example of wrongness:

int condA=1, condB=2;

if (condA!=0 && condB!=0) {
    // correct!
}
if ((condA & condB)!=0) {
    // never executed
}

here you have two conditions, both are non-zero; but the bitwise & results in zero.

Javier
  • 9,888
  • 1
  • 26
  • 35
  • @Javier: Thank you for answering, but I’m a little confused. I’m working in java, and this code does not compile. `(condA && condB)` errors, because the && does not work for 2 `int`s, only 2 booleans. `(condA & condB)` while correct, evaluates to an `int ` and in java we cannot say `if(int)` so it errors too. You’re the first to understand what I’m looking for though- exactly that _example of wrongness_. – Deerasha Apr 14 '11 at 19:39
  • haven't used Java in a long time... try `(Boolean(condA) && Boolean(condB))` (i think `Boolean(x)` is `true` for non-zero integers, right?) – Javier Apr 14 '11 at 20:32
  • Nope @Javier: Cannot cast from int to boolean. – Deerasha Apr 14 '11 at 20:35
  • what about `((condA!=0) && (condB!=0))` ? – Javier Apr 14 '11 at 20:41
  • @Javier yay it compiles, but the "wrongness" is no longer illustrated `if (((condA!=0) && (condB!=0))) { System.out.println("correct"); } if (((condA!=0) & (condB!=0))) { System.out.println("never executed?"); }` executes both print statements. – Deerasha Apr 14 '11 at 21:10
  • the second one would be `if((condA & condB) != 0) {...` – Javier Apr 14 '11 at 21:40