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 ответов:
он переполняется, потому что число отрицательное.
попробуйте это, и он будет работать:
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
в HexLong.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();