Tengo el siguiente código...
int Val=-32768;
String Hex=Integer.toHexString(Val);
Esto equivale a ffff8000
int FirstAttempt=Integer.parseInt(Hex,16); // Error "Invalid Int"
int SecondAttempt=Integer.decode("0x"+Hex); // Error "Invalid Int"
Entonces, inicialmente, convierte el valor -32768 en una cadena hexadecimal ffff8000, pero luego no puede convertir la cadena hexadecimal de nuevo en un entero.
En .Net
funciona como esperaba, y returns -32768
.
Sé que podría escribir mi propio método para convertir esto yo mismo, pero me pregunto si me estoy perdiendo algo o si esto es realmente un error.
int firstAttempt = 5;
Respuestas:
Se desborda, porque el número es negativo.
Prueba esto y funcionará:
int n = (int) Long.parseLong("ffff8000", 16);
fuente
String Hex=Integer.toHexString("xyz");
cómo recuperar la cadena del hexadecimal como "xyz"int val = -32768; String hex = Integer.toHexString(val); int parsedResult = (int) Long.parseLong(hex, 16); System.out.println(parsedResult);
Así es como puedes hacerlo.
La razón por la que no funciona a su manera:
Integer.parseInt
toma un int firmado, mientras quetoHexString
produce un resultado sin firmar. Entonces, si inserta algo mayor que0x7FFFFFF
, se lanzará un error automáticamente. Si lo analiza como en sulong
lugar, seguirá estando firmado. Pero cuando lo devuelva a int, se desbordará al valor correcto.fuente
int
a Hex:Hex a
int
:Integer.valueOf(hexString, 16).intValue();
También puede utilizar en
long
lugar deint
(si el valor no se ajusta a losint
límites):Hex a
long
:Long.valueOf(hexString, 16).longValue()
long
a Hexfuente
Vale la pena mencionar que Java 8 tiene los métodos
Integer.parseUnsignedInt
yLong.parseUnsignedLong
eso hace lo que querías, específicamente:Integer.parseUnsignedInt("ffff8000",16) == -32768
El nombre es un poco confuso, ya que analiza un entero con signo de una cadena hexadecimal, pero hace el trabajo.
fuente
Intente usar la clase BigInteger, funciona.
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());
fuente
Como Integer.toHexString (byte / integer) no funciona cuando intenta convertir bytes firmados como caracteres decodificados UTF-16, debe usar:
Integer.toString(byte/integer, 16);
o
String.format("%02X", byte/integer);
reverso que puedes usar
Integer.parseInt(hexString, 16);
fuente
El método parseInt de Java es en realidad un montón de código que come hexadecimal "falso": si desea traducir -32768, debe convertir el valor absoluto en hexadecimal y luego anteponer la cadena con '-'.
Hay una muestra del archivo Integer.java:
public static int parseInt(String s, int radix)
La descripción es bastante explícita:
* 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
fuente
Usar
Integer.toHexString(...)
es una buena respuesta. Pero personalmente prefiero usarString.format(...)
.Pruebe esta muestra como prueba.
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();
fuente
El siguiente código funcionaría:
int a=-32768; String a1=Integer.toHexString(a); int parsedResult=(int)Long.parseLong(a1,16); System.out.println("Parsed Value is " +parsedResult);
fuente
Jeje, curioso. Creo que esto es un "error intencional", por así decirlo.
La razón subyacente es cómo se escribe la clase Integer. Básicamente, parseInt está "optimizado" para números positivos. Cuando analiza la cadena, genera el resultado de forma acumulativa, pero se niega. Luego cambia el signo del resultado final.
Ejemplo:
66 = 0x42
analizado como:
4*(-1) = -4 -4 * 16 = -64 (hex 4 parsed) -64 - 2 = -66 (hex 2 parsed) return -66 * (-1) = 66
Ahora, veamos su ejemplo 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.
Editar (adición): para que parseInt () funcione "consistentemente" para -Integer.MAX_VALUE <= n <= Integer.MAX_VALUE, habrían tenido que implementar la lógica para "rotar" al alcanzar -Integer.MAX_VALUE en el resultado acumulativo, comenzando de nuevo en el extremo máximo del rango de enteros y continuando hacia abajo desde allí. Por qué no hicieron esto, habría que preguntarle a Josh Bloch oa quien sea que lo implementó en primer lugar. Podría ser solo una optimización.
Sin embargo,
Hex=Integer.toHexString(Integer.MAX_VALUE); System.out.println(Hex); System.out.println(Integer.parseInt(Hex.toUpperCase(), 16));
funciona bien, solo por esta razón. En el código fuente de Integer puedes encontrar este comentario.
// Accumulating negatively avoids surprises near MAX_VALUE
fuente
// Accumulating negatively avoids surprises near MAX_VALUE
-> pero introduce sorpresas inferiores 0 ^^