У меня есть следующий код ...
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
.
Я знаю, что мог бы написать свой собственный небольшой метод, чтобы преобразовать это сам, но мне просто интересно, что-то мне не хватает или это действительно ошибка?
int firstAttempt = 5;
Ответы:
Он переполняется, потому что число отрицательное.
Попробуйте это, и это сработает:
int n = (int) Long.parseLong("ffff8000", 16);
источник
String Hex=Integer.toHexString("xyz");
как вернуть строку из шестнадцатеричного значения как «xyz»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
в Hex:Hex для
int
:Integer.valueOf(hexString, 16).intValue();
Вы также можете использовать
long
вместоint
(если значение не соответствуетint
границам):Hex для
long
:Long.valueOf(hexString, 16).longValue()
long
в Hexисточник
Стоит отметить , что Java 8 имеет методы
Integer.parseUnsignedInt
иLong.parseUnsignedLong
что делает то , что вы хотите, а именно:Integer.parseUnsignedInt("ffff8000",16) == -32768
Имя немного сбивает с толку, поскольку оно анализирует целое число со знаком из шестнадцатеричной строки, но выполняет свою работу.
источник
Попробуйте использовать класс 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());
источник
Поскольку Integer.toHexString (byte / integer) не работает, когда вы пытаетесь преобразовать подписанные байты, такие как декодированные символы UTF-16, вы должны использовать:
Integer.toString(byte/integer, 16);
или же
String.format("%02X", byte/integer);
обратное вы можете использовать
Integer.parseInt(hexString, 16);
источник
Java-метод parseInt на самом деле представляет собой набор кода, поедающего "ложное" шестнадцатеричное значение: если вы хотите перевести -32768, вы должны преобразовать абсолютное значение в шестнадцатеричное, а затем добавить строку с '-'.
Вот пример файла Integer.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
источник
Использование
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();
источник
Ниже код будет работать:
int a=-32768; String a1=Integer.toHexString(a); int parsedResult=(int)Long.parseLong(a1,16); System.out.println("Parsed Value is " +parsedResult);
источник
Хе-хе, любопытно. Я считаю, что это, так сказать, «внутренняя ошибка».
Основная причина в том, как написан класс Integer. По сути, 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.
Изменить (добавление): для того, чтобы parseInt () работал «последовательно» для -Integer.MAX_VALUE <= n <= Integer.MAX_VALUE, им пришлось бы реализовать логику для «поворота» при достижении -Integer.MAX_VALUE в совокупный результат, начиная с максимального конца целочисленного диапазона и продолжая оттуда вниз. Почему они этого не сделали, нужно было бы спросить Джоша Блоха или того, кто реализовал это в первую очередь. Возможно, это просто оптимизация.
Тем не мение,
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
источник
// Accumulating negatively avoids surprises near MAX_VALUE
-> но он преподносит сюрпризы ниже 0 ^^