Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Converting Hex in Java, wrong value with negative values

Tags:

java

decimal

hex

I have seen several questions on the topic mentioned in the subject (e.g this one), but it seems to me that none of them provided this example. I'm using Java7 and I want to convert a String representing an hexadecimal or a decimal into an Integer or Long value (depends on what it represents) and I do the following:

public Number getIntegerOrLong(String num) {
    try {
        return Integer.decode(num);
    } catch (NumberFormatException nf1) {
        final long decodedLong = Long.decode(num);
        if ((int) decodedLong == decodedLong) {//used in Java8 java.util.Math.toIntExact()
            return (int) decodedLong;
        }
        return decodedLong;
    }
}

When I use a String representing a decimal number everything is ok, the problem are arising with negative hexadecimals

Now, If I do:

String hex = "0x"+Integer.toHexString(Integer.MIN_VALUE);
Object number = getIntegerOrLong(hex);
assertTrue(number instanceof Integer):

fails, because it returns a Long. Same for other negative integer values.

Moreover, when I use Long.MIN_VALUE like in the following:

String hex = "0x"+Integer.toHexString(Long.MIN_VALUE);
Object number = getIntegerOrLong(hex);
assertTrue(number instanceof Long):

fails, because of NumberFormatException with message:

java.lang.NumberFormatException: For input string: "8000000000000000"

I also tried with other random Long values (so within the Long.MIN_VALUE and Long.MAX_VALUE, and it fails as well when I have negative numbers. E.g.

the String with the hexadecimal 0xc0f1a47ba0c04d89 for the Long number -4,543,669,698,155,229,815 returns:

java.lang.NumberFormatException: For input string: "c0f1a47ba0c04d89"

How can I fix the script to obtain the desired behavior?

like image 950
mat_boy Avatar asked Jul 03 '26 23:07

mat_boy


1 Answers

Long.decode and Integer.decode do not accept complemented values such as returned by Integer.toHexString : the sign should be represented as a leading - as described by the DecodableString grammars found in the javadoc.

The sequence of characters following an optional sign and/or radix specifier ("0x", "0X", "#", or leading zero) is parsed as by the Long.parseLong method with the indicated radix (10, 16, or 8). This sequence of characters must represent a positive value or a NumberFormatException will be thrown. The result is negated if first character of the specified String is the minus sign

If you can change the format of your input String, then produce it with Integer.toString(value, 16) rather than Integer.toHexString(value).

If you can switch to Java 8, use parseUnsignedInt/Long.

like image 79
Aaron Avatar answered Jul 05 '26 13:07

Aaron