Java Reference
In-Depth Information
< Day Day Up >
Puzzle 33: Looper Meets the Wolfman
Provide a declaration for
i
that turns this loop into an infinite loop. This one doesn't require the use
of any release 5.0 features:
while (i != 0 && i == -i) {
}
Solution 33: Looper Meets the Wolfman
Yet another puzzling looper. In the
boolean
expression
(i != 0 && i == -i
), the unary minus
operator is applied to
i
, which implies that its type must be numeric: It is illegal to apply the unary
minus operator to a non-numeric operand. Therefore, we are looking for a nonzero numeric value
that is equal to its own negation. NaN does not satisfy this property, as it is not equal to any value,
so
i
must represent an actual number. Surely there is no number with this property?
Well, there is no real number with this property, but none of Java's numeric types model the real
numbers perfectly. Floating-point values are represented with a sign bit; a significand, informally
known as the
mantissa
; and an exponent. No floating-point value other than 0 is equal to itself with
the sign bit flipped, so the type of
i
must be integral.
The signed integral types use
two's-complement arithmetic
: To negate a value, you flip every bit and
add 1 to the result [JLS 15.15.4]. One big advantage of two's-complement arithmetic is that there is
a unique representation for 0. If you negate the
int
value
0
, you get
0xffffffff + 1
, which is
0
.
There is, however, a corresponding disadvantage. There exist an even number of
int
values— 2
32
to
be precise— and one of these values is used to represent 0. That leaves an odd number of
int
values
to represent positive and negative integers, which means that there must be a different number of
positive and negative
int
values. This in turn implies that there is at least one
int
value whose
negation cannot be correctly represented as an
int
value.
In fact, there is exactly one such
int
value, and it is
Integer.MIN_VALUE
, or
-2
31
. Its hexadecimal
representation is
0x8000000
. The sign bit is 1, and all the other bits are 0. If we negate this value,
we get
0x7fffffff + 1
, which is
0x8000000
, or
Integer.MIN_VALUE
! In other words,
Integer.MIN_VALUE
is its own negation
, as is
Long.MIN_VALUE
. Negating either of these values
causes an overflow, but Java ignores overflows in integer computations. The results are well
defined, even if they are not always what you want them to be.
This declaration will make the
boolean
expression
(i != 0 && i == -i)
evaluate to
true
,
causing the loop to spin indefinitely:
Search WWH ::
Custom Search