So I finally got my code to work with:
if((choice == 1 ) || (choice == 2) || (choice == 3) || (choice == 4)){
but why does:
if(choice == (1 | 2)) {
result in a logic/math error? for example, if I enter "3" then the code accepts it and processes it as successful. The code snippet is as follows:
while(counter == 0){
try{
int choice = Integer.parseInt(input.nextLine());
if(choice == (1 | 2)){
System.out.println("You got it!");
++counter;
}else{
System.out.println("Try again");
}
}
catch(NumberFormatException Exception){
System.out.println("You did something wrong");
}
}
And if I do:
if(choice == (1 | 2 | 3 | 4 )){
then it will only accept 7 as far as I can tell. What exactly is going on when it is compiling and is there a way to shorten the solution I found?
The issue here is that
if (choice == (1 | 2)) { ... }
doesn't mean "if choice is equal to one or equal to two, then... ." Instead, Java is interpreting 1 | 2 as "the bitwise OR of the two numbers 1 and 2," since a single vertical bar represents the bitwise OR operator. If you take the bitwise OR of 1 and 2, you get the number 3 (if you know about binary numbers, see if you can confirm why this is the case), so your if statement is completely equivalent to
if (choice == 3) { ... }
which is why you're seeing the behavior that you're seeing.
Similarly, if you write
if (choice == (1 | 2 | 3 | 4)) { ... }
Java interprets the expression 1 | 2 | 3 | 4 as "the bitwise OR of the numbers 1, 2, 3, and 4," which works out to 7.
If you have a collection of values and you want to test if a specific value is equal to any of those values, one option is, as you've noted, to have a bunch of independent equality tests. If you have a very large number of values, you may want to use something like a HashSet instead.
The expression 1 | 2 is a bitwise OR, so the result is 3, and if(choice == (1 | 2)) is actually the same as if(choice == 3).
The | only acts as a logical OR between boolean values.
See also the Java Language Specification, section 15.22.1 Integer Bitwise Operators &, ^, and |:
When both operands of an operator
&,^, or|are of a type that is convertible (§5.1.8) to a primitive integral type, binary numeric promotion is first performed on the operands (§5.6.2).The type of the bitwise operator expression is the promoted type of the operands.
[..]
For
|, the result value is the bitwise inclusive OR of the operand values.
and section 15.22.2 Boolean Logical Operators &, ^, and |
When both operands of a
&,^, or|operator are of typebooleanorBoolean, then the type of the bitwise operator expression isboolean. In all cases, the operands are subject to unboxing conversion (§5.1.8) as necessary.[..]
For
|, the result value isfalseif both operand values arefalse; otherwise, the result istrue.
As to a shorter solution, trivially your initial code is probably as simple as it can get. If you want to scale it to a larger number of conditions, then consider:
1 <= choice && choice <= 4 - if accepted values of choice are a contiguous rangeArrays.binarySearch(new int[1, 2, 3, 4], choice) >= 0 - requires that the array is sortedArrays.asList(1, 2, 3, 4).contains(choice) - this has overhead, because this converts the integer values to objects.Convert your code to a switch (not immediately shorter, until we get pattern-matching switch in a future Java version, but can be clearer with a lot of values)
switch(choice) {
case 1:
case 2:
case 3:
case 4:
// if 1, 2, 3, 4
// do things
break;
case 5:
// else if 5
// do other things
break
default:
// else
// do something else
break;
}
Except the first and the last, these options have the downside that it is not immediately clear what you are checking for. In those case, clear code trumps 'short' code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With