Java Reference
In-Depth Information
< Day Day Up >
Puzzle 1: Oddity
The following method purports to determine whether its sole argument is an odd number. Does the
method work?
public static boolean isOdd(int i) {
return i % 2 == 1;
}
Solution 1: Oddity
An odd number can be defined as an integer that is divisible by 2 with a remainder of 1. The
expression
i % 2
computes the remainder when
i
is divided by 2, so it would seem that this
program ought to work. Unfortunately, it doesn't; it returns the wrong answer one quarter of the
time.
Why one quarter? Because half of all
int
values are negative, and the
isOdd
method fails for all
negative odd values. It returns
false
when invoked on any negative value, whether even or odd.
This is a consequence of the definition of Java's remainder operator (
%
). It is defined to satisfy the
following identity for all
int
values
a
and all nonzero
int
values
b
:
(a / b) * b + (a % b) == a
In other words, if you divide
a
by
b
, multiply the result by
b
, and add the remainder, you are back
where you started [JLS 15.17.3]. This identity makes perfect sense, but in combination with Java's
truncating integer division operator [JLS 15.17.2], it implies that
when the remainder operation
returns a nonzero result, it has the same sign as its left operand.
The
isOdd
method and the definition of the term
odd
on which it was based both assume that all
remainders are positive. Although this assumption makes sense for some kinds of division
[Boxing]
,
Java's remainder operation is perfectly matched to its integer division operation, which discards the
fractional part of its result.
When
i
is a negative odd number,
i % 2
is equal to
-1
rather than
1
, so the
isOdd
method
incorrectly returns
false
. To prevent this sort of surprise,
test that your methods behave properly
when passed negative, zero, and positive values for each numerical parameter.
The problem is easy to fix. Simply compare
i % 2
to
0
rather than to
1
, and reverse the sense of the
comparison:
Search WWH ::
Custom Search