Java преобразование int в hex и обратно


у меня есть следующий код...

int Val=-32768;
String Hex=Integer.toHexString(Val);

это приравнивается к ffff8000

int FirstAttempt=Integer.parseInt(Hex,16); // Error "Invalid Int"
int SecondAttempt=Integer.decode("0x"+Hex);  // Error "Invalid Int"

Итак, первоначально он преобразует значение -32768 в шестнадцатеричную строку ffff8000, но затем он не может преобразовать шестнадцатеричную строку обратно в целое число.

на .Net он работает так, как я ожидал, и returns -32768.

Я знаю, что я мог бы написать свой собственный маленький метод, чтобы преобразовать это сам, но мне просто интересно, если я чего-то не хватает, или если это действительно ошибка?

9 55

9 ответов:

он переполняется, потому что число отрицательное.

попробуйте это, и он будет работать:

int n = (int) Long.parseLong("ffff8000", 16);
int val = -32768;
String hex = Integer.toHexString(val);

int parsedResult = (int) Long.parseLong(hex, 16);
System.out.println(parsedResult);

вот как вы можете сделать это.

причина, почему это не работает ваш путь:Integer.parseInt принимает знак int, в то время как toHexString выдает беззнаковый результат. Так что если вы вставляете что-то выше, чем 0x7FFFFFF, ошибка будет выдана автоматически. Если вы разбираете его как long вместо этого он все равно будет подписан. Но когда вы вернете его обратно в int, он переполнится до правильного значения.

  • int to Hex:

    Integer.toHexString(intValue);
    
  • Hex to int:

    Integer.valueOf(hexString, 16).intValue();
    

вы также можете использовать long вместо int (если значение не соответствует int границ):

  • Hex to long:

    Long.valueOf(hexString, 16).longValue()
    
  • long в Hex

    Long.toHexString(longValue)
    

попробуйте использовать класс BigInteger, он работает.

int Val=-32768;
String Hex=Integer.toHexString(Val);

//int FirstAttempt=Integer.parseInt(Hex,16); // Error "Invalid Int"
//int SecondAttempt=Integer.decode("0x"+Hex);  // Error "Invalid Int"
BigInteger i = new BigInteger(Hex,16);
System.out.println(i.intValue());

стоит отметить, что Java 8 имеет методы Integer.parseUnsignedInt и Long.parseUnsignedLong это делает то, что вы хотели, в частности:

Integer.parseUnsignedInt("ffff8000",16) == -32768

название немного сбивает с толку, так как он анализирует целое число из шестнадцатеричной строки, но это делает работу.

Как Целое.toHexString (byte / integer) не работает, когда вы пытаетесь преобразовать подписанные байты, такие как декодированные символы UTF-16, которые вы должны использовать:

Integer.toString(byte/integer, 16);

или

String.format("%02X", byte/integer);

обратный вы можете использовать

Integer.parseInt(hexString, 16);

метод parseInt Java является actally кучей кода, едящего "ложный" hex: если вы хотите перевести -32768, вы должны преобразовать абсолютное значение в hex, а затем добавить строку с '-'.

есть образец целого числа.java-файл:

public static int parseInt(String s, int radix)

описание довольно явный :

* Parses the string argument as a signed integer in the radix 
* specified by the second argument. The characters in the string 
...
...
* parseInt("0", 10) returns 0
* parseInt("473", 10) returns 473
* parseInt("-0", 10) returns 0
* parseInt("-FF", 16) returns -255

хехе, любопытно. Я думаю, что это "интенциональная ошибка", так сказать.

основная причина заключается в том, как записывается целочисленный класс. В принципе, parseInt "оптимизирован" для положительных чисел. Когда он анализирует строку, он строит результат кумулятивно, но отрицается. Затем он переворачивает знак конечного результата.

пример:

66 = 0x42

разбирается, как:

4*(-1) = -4
-4 * 16 = -64 (hex 4 parsed)

-64 - 2 = -66 (hex 2 parsed)

return -66 * (-1) = 66

теперь, давайте посмотрим на ваш образец FFFF8000

16*(-1) = -16 (first F parsed)
-16*16 = -256 

-256 - 16 = -272 (second F parsed)
-272 * 16 = -4352 

-4352 - 16 = -4368 (third F parsed)
-4352 * 16 = -69888

-69888 - 16 = -69904 (forth F parsed)
-69904 * 16 = -1118464 

-1118464 - 8 = -1118472 (8 parsed)
-1118464 * 16 = -17895552 

-17895552 - 0 = -17895552 (first 0 parsed)
Here it blows up since -17895552 < -Integer.MAX_VALUE / 16 (-134217728). 
Attempting to execute the next logical step in the chain (-17895552 * 16)
would cause an integer overflow error.

Edit (addition): для того, чтобы parseInt () работал "последовательно" для-Integer.Массив ,

Hex=Integer.toHexString(Integer.MAX_VALUE);
System.out.println(Hex);
System.out.println(Integer.parseInt(Hex.toUpperCase(), 16));

работает просто отлично, именно по этой причине. В источнике для Integer вы можете найти этот комментарий.

// Accumulating negatively avoids surprises near MAX_VALUE

используя Integer.toHexString(...) - хороший ответ. Но лично предпочитаю использовать String.format(...).

попробуйте этот образец в качестве теста.

byte[] values = new byte[64];
Arrays.fill(values, (byte)8);  //Fills array with 8 just for test
String valuesStr = "";
for(int i = 0; i < values.length; i++)
    valuesStr += String.format("0x%02x", values[i] & 0xff) + " ";
valuesStr.trim();