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

StackOverflow https://stackoverflow.com/questions/845230

Вопрос

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)

Как дела?

Это было полезно?

Решение

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

Другие советы

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

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

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

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

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

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

Таким образом, правильная обратная операция, вероятно, Integer.parseUnsignedInt это было представлено как часть 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));
    }

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

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

Вам нужно включить отрицательный знак.

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

Integer min = Integer.MIN_VALUE + 1;

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

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

Кажется, это работает для меня:

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».

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top