Today, I stumbled upon Java Tutorial Operators page.
I glanced the list, wondering if I know what each operator does. As you might have guessed from the title, I failed. Luckily, I failed at only two operators.
The modulo operator %
While mostly defined in the same fashion, implementations of modulo or reminder operator differ when it comes to the sign of a result. For example, a modulo operator in Python might yield a different result than a modulo operator in Java, using the exact same data. Try it out for yourself, evaluate the expression
-1 % 2 for instance.
It boils down to the decision language designers made when defining the operator. Recall that in an expression
a % b = c,
a is said to be the dividend and
b the divisor. Some decided
c should have the same sign as the dividend, others divisor. Java chose dividend, Python divisor.
Missing this fact could lead to some fun late night debugging sessions. Consider the following example:
It works wonderful with a positive argument. But since the definition of an odd number is quite natural for any negative integer too, does
isOdd(-1) produce a correct result?
Java uses the dividend when determining the sign of a modulo operation. Therefore, if the argument we pass to
isOdd is negative, the modulo operation yields a negative result. In our case
-1 % 2 == -1, and
isOdd(-1) == false. The result is not what one would expect.
A quick fix could apply absolute value to a dividend. A better solution, albeit a bit cryptic, would be to just check the last bit of a number and avoid the modulo operator altogether:
The unsigned right shift
The second operator I was having trouble with was
>>>. I couldn’t tell the difference with
>> operator, so I had to check the definition:
>>> is an unsigned right shift whereas
>> is signed. Confused? Read on.
>> operator uses the most-significant bit value when shifting a bit pattern, whereas
>>> always uses
Suppose we’re operating with 4-bit two’s complement numbers. Take a binary number, e.g.
0001. The most significant bit is
0. Performing a shift, say
0001 >> 1, the value you’ll be shifting with is
Now consider the binary number
1001. The most significant bit in this case is
1, so the value you’ll be shifting with is
0001 >> 1 == 0000 1001 >> 1 == 1100
Regardless of the most significant bit value, an unsigned right shift operator
>>> always uses
0 as the shifting value.
0001 will be shifted with
0 as before, but so will
0001 >>> 1 = 0000 1001 >>> 1 = 0100
You may notice there is no unsigned left shift operator. Any nontrivial
<< shift will actually move the significant bit out of the picture:
1001 << 1 == 0010. Shifting by 1 to the left will transform -7 to 2, changing signs along the way. Therefore, the
<< operator itself is already unsigned.