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) 

Что происходит?

    Задокументировано, что Integer.toHexString возвращает строковое представление целого в качестве значения без знака – в то время как Integer.parseInt принимает подписанный int. Если вы используете 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».

    Давайте будем гением компьютера.