Thursday, January 17, 2008

Java Integer.decode broken

If you're aware of two's compliment representation of integers, you can probably guess the output of the following line of Java:

System.out.println(Integer.toHexString(-1));

Sure enough, you get this:

ffffffff

Knowing that, what do you think the result of this line might be?

System.out.println(Integer.decode("0xffffffff"));

Would you believe NumberFormatException: For input string: "ffffffff"? The reason is that decode works on signed values. Ugly with a capital Ug. Decode works as expected on hexadecimal values in which the most significant bit is clear. But here, that high bit is set. The decode function expects a negative hex value where ever you'd use a negative decimal value.

Now, what would be a proper punishment for the kind of protohuman homunculus who would use a sign with a hexadecimal number? Fifty lashes with a wet noodle for the addled mind that thought this was a good idea:

Integer.toHexString(Integer.decode("-0x1"));
ffffffff

Most sane programmers find this highly annoying. There's a bug dated in 1999, (and several dupes) in the Java bug database for this, and its counterpart bug in Long. What an embarrassment.

One work-around (for integers) is to use a Long when you expect a hex number with the sign bit set.

int thisIsTotallyWeak = Long.decode("0xffffffff").intValue();

2 comments:

  1. Negative hex numbers bug me because hex is just a compact representation of binary. So, when I use hex I'm thinking of bits, not the integer, character, color, floating point number, or whatever they represent.

    ReplyDelete
  2. Whith JDK7 is possible to use binary literals, like 0b1010. However, Integer.decode doesn't recognize "0b1010" input!!!

    How annoying.

    ReplyDelete