Any trap which we should beware of Integer.MIN_VALUE == -Integer.MIN_VALUE == Math.abs(Integer.MIN_VALUE)
I realize the below code holds true
Integer.MIN_VALUE == -Integer.MIN_VALUE == Math.abs(Integer.MIN_VALUE)
This is because when we negate -开发者_开发百科2147483648
, it should become +2147483648
. Since the maximum positive integer can be represented in Java is +2147483647
, integer overflow will occur. When overflow occur, it becomes -2147483648
again.
I was wondering, is there any trap we should keep an eye on it, for the above situation?
The biggest trap is the slient overflow of which this is an example.
Similar examples.
Long.MIN_VALUE == -Long.MIN_VALUE;
0.0d == -0.0d
0.0f == -0.0f
Double.NaN != Double.NaN
Float.NaN != Float.NaN
Double.compare(Double.NaN, 0) == 1 but Double.NaN > 0 is false
Float.compare(Float.NaN, 0) == 1 but Float.NaN > 0 is false
FYI
Byte.MIN_VALUE != -Byte.MIN_VALUE;
Short.MIN_VALUE != -Short.MIN_VALUE;
Character.MIN_VALUE == -Character.MIN_VALUE;
Every function, mechanism, feature, gadget, widget, fidget, and blidget in the history of programming has input and and output limitations.
The trap to avoid for this, and for all features, is do not assume there are no limits.
Edit: This doesn't mean you can't use these limits to your advantage, because you most certainly can. Just make sure that anything 'tricky', 'cool', or 'hackish' gets it's share of documentation, or they next guy to come into the code (or even you) is going to wonder wtf is going on.
I can't imagine a good reason for writing any code that depends on overflow. I'd describe anything that actually worked that way as a trap in itself, because it's functioning is dependent on shortcomings in the system (i.e. numeric size limits) rather than the clear and explicit meaning of the code (largest or smallest value).
The only one I can come up with, is if you end up writing your own absolute-value implementation, where you (naively) do
return i < 0 ? -i : i;
(Note however, that Math.abs(Integer.MIN_VALUE)
indeed returns a negative result (Integer.MIN_VALUE
), so what is the correct behavior is up for discussion when writing an abs-method.)
I saw something like this today:
return Math.abs(obj.hashCode()) % partitions;
The returned partition number should be non-negative so Math.abs
is used to "ensure" that the left side is non-negative, since the obnoxious %
implementation could return a negative number otherwise. But as you might have guessed this code is broken since hashCode()
is an integer and it might return Integer.MIN_VALUE
.
One possible fix would be to do a cast to long
but I prefer to just set the parenthesis a little different:
return Math.abs(obj.hashCode() % partitions);
Update: Actually this version is better since it doesn't rely on Math.abs
at all:
return (obj.hashCode() & Integer.MAX_VALUE) % partitions;
It will yield different partition numbers for negative hash codes than the version above, but normally you shouldn't care about that if you partition by hash code.
精彩评论