Java convirtiendo int a hexadecimal y viceversa

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 hexagonal ffff8000, pero luego no puede convertir la cadena hexadecimal nuevamente en un Entero.

En .Net funciona como esperaba, y returns -32768 .

Sé que podría escribir mi propio pequeño método para convertir esto, pero me pregunto si me falta algo, o si esto es realmente un error.

Se desborda, porque el número es negativo.

Prueba esto y funcionará:

 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); 

Así es como puedes hacerlo.

La razón por la cual no funciona a su manera: Integer.parseInt toma un int firmado, mientras que toHexString produce un resultado sin signo. Entonces, si inserta algo superior a 0x7FFFFFF , se 0x7FFFFFF un error automáticamente. Si lo analiza en su lugar, se seguirá firmando. Pero cuando lo vuelves a int, se desbordará al valor correcto.

  • int a Hex:

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

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

También puede usar long lugar de int (si el valor no se ajusta a los límites int ):

  • Hexágono a long :

     Long.valueOf(hexString, 16).longValue() 
  • long para maleficio

     Long.toHexString(longValue) 

Intenta 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()); 

Vale la pena mencionar que Java 8 tiene los métodos Integer.parseUnsignedInt y Long.parseUnsignedLong que hace lo que usted quería, 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.

Como Integer.toHexString (byte / integer) no funciona cuando intenta convertir bytes firmados como caracteres decodificados UTF-16 que debe usar:

 Integer.toString(byte/integer, 16); 

o

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

reversa puedes usar

 Integer.parseInt(hexString, 16); 

El método parseInt de Java es actalmente un montón de código que come hexágono “falso”: si quieres traducir -32768, debes convertir el valor absoluto en hexadecimal, 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 

Jeje, curioso. Creo que esto es un “error intentianal”, 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, construye el resultado de forma acumulativa, pero negada. Luego, voltea 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 tu 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 el parseInt () funcione "coherentemente" para -Integer.MAX_VALUE < = n <= Integer.MAX_VALUE, tendrían que implementar lógica para "rotar" al llegar a -Integer.MAX_VALUE en el resultado acumulativo, comenzando de nuevo en el extremo máximo del rango entero y continuando hacia abajo desde allí. Por qué no lo hicieron, uno tendría que preguntarle a Josh Bloch o quién lo implementó en primer lugar. Puede 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 origen de Integer puede encontrar este comentario.

 // Accumulating negatively avoids surprises near MAX_VALUE 

Usar Integer.toHexString(...) es una buena respuesta. Pero personalmente prefiero usar String.format(...) .

Pruebe esta muestra como una 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();