Java отрицательный int в шестнадцатеричный и обратно не работает

public class Main3 {
    public static void main(String[] args) {
        Integer min = Integer.MIN_VALUE;
        String minHex = Integer.toHexString(Integer.MIN_VALUE);

        System.out.println(min + " " + minHex);
        System.out.println(Integer.parseInt(minHex, 16));
    }
}

Дает

-2147483648 80000000
Exception in thread "main" java.lang.NumberFormatException: For input string: "80000000"
    at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48)
    at java.lang.Integer.parseInt(Integer.java:459)
    at Main3.main(Main3.java:7)

Как дела?


person Maxim Veksler    schedule 10.05.2009    source источник


Ответы (6)


Документировано, что Integer.toHexString возвращает строковое представление целого числа как беззнаковое значение, а Integer.parseInt принимает знаковое int. Если вы вместо этого используете Integer.toString(value, 16), вы получите то, что хотите.

person dhn    schedule 10.05.2009
comment
Было бы здорово, если бы существовал способ преобразования из шестнадцатеричного в int / long, просто помещая биты, не заботясь о знаке. Таким образом можно было бы конвертировать туда и обратно с минимальными накладными расходами. - person akostadinov; 28.03.2013

Меня это всегда раздражало. Если вы инициализируете int шестнадцатеричным литералом, вы можете использовать полный диапазон положительных значений до 0xFFFFFF; все, что больше 0x7FFFFF, действительно будет отрицательным значением. Это очень удобно для битовой маскировки и других операций, когда вас интересует только расположение битов, а не их значения.

Но если вы используете Integer.parseInt () для преобразования строки в целое число, все, что больше "0x7FFFFFFF", рассматривается как ошибка. Вероятно, есть веская причина, по которой они так поступили, но это все равно расстраивает.

Самый простой обходной путь - использовать вместо этого Long.parseLong (), а затем преобразовать результат в int.

int n = (int)Long.parseLong(s, 16);

Конечно, вам следует делать это только в том случае, если вы уверены, что число будет в диапазоне Integer.MIN_VALUE..Integer.MAX_VALUE.

person Alan Moore    schedule 10.05.2009

Согласно документации, toHexString < / a> возвращает "строковое представление целочисленного аргумента как беззнаковое целое число с основанием 16."

Таким образом, правильная обратная операция, вероятно, будет _ 2_, который был представлен как часть Java 8:

public class Main3 {
    public static void main(String[] args) {
        Integer min = Integer.MIN_VALUE;
        String minHex = Integer.toHexString(Integer.MIN_VALUE);

        System.out.println(min + " " + minHex);
        System.out.println(Integer.parseUnsignedInt(minHex, 16));
    }
person Sylvain Leroux    schedule 06.12.2014

Попробуй это:

public class Main3 {
    public static void main(String[] args) {
        Integer min = Integer.MIN_VALUE;
        String minHex = Integer.toHexString(Integer.MIN_VALUE);

        System.out.println(min + " " + minHex);
        System.out.println(Integer.parseInt( "-" + minHex, 16));
    }

}

чтобы получить это:

-2147483648 80000000
-2147483648
person alphazero    schedule 10.05.2009

Вам необходимо включить знак минус.

У меня нет доступа, чтобы проверить это прямо сейчас, но я готов поспорить, если бы вы вместо этого попробовали это значение:

Integer min = Integer.MIN_VALUE + 1;

Он не будет бомбить, но даст вам положительное число (не отрицательное), когда вы запустите ParseInt(min,16).

В строке битов действительно недостаточно информации для определения знака в этом контексте, поэтому вам необходимо ее предоставить. (рассмотрим случай, когда вы используете min = "F". Это +/- F? Если вы преобразовали его в биты и увидели 1111, и, вы знали, что это байт, вы могли бы сделать вывод, что он отрицательный, но это много если.

person Michael Haren    schedule 10.05.2009

Мне кажется, это работает:

public class Main3 {
public static void main(String[] args) {
    Integer min = Integer.MIN_VALUE;
    String minHex = Integer.toHexString(Integer.MIN_VALUE);

    System.out.println(min + " " + minHex);
    System.out.println((int)Long.parseLong(minHex, 16));
}
}

Целое число анализируется как «длинное число со знаком», которое обрабатывает такое большое положительное число, а затем возвращается знак путем преобразования его в «int».

person Fabrice LARRIBE    schedule 27.11.2014