J'ai le code suivant...
int Val=-32768;
String Hex=Integer.toHexString(Val);
Cela équivaut à ffff8000
int FirstAttempt=Integer.parseInt(Hex,16); // Error "Invalid Int"
int SecondAttempt=Integer.decode("0x"+Hex); // Error "Invalid Int"
Ainsi, initialement, il convertit la valeur -32768 en une chaîne hexagonale ffff8000, mais ne peut ensuite pas convertir la chaîne hexadécimale en un entier.
Dans .Net
ça marche comme je le pensais, et returns -32768
.
Je sais que je pourrais écrire ma propre petite méthode pour convertir cela moi-même, mais je me demande simplement si quelque chose me manque ou s'il s'agit véritablement d'un bug?
Il déborde, car le nombre est négatif.
Essayez ceci et cela fonctionnera:
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);
C'est comme ça que tu peux le faire.
La raison pour laquelle cela ne fonctionne pas à votre façon: Integer.parseInt
prend un entier signé, tandis que toHexString
produit un résultat non signé. Donc, si vous insérez quelque chose de plus grand que 0x7FFFFFF
, une erreur sera automatiquement générée. Si vous analysez plutôt long
, il sera quand même signé. Mais lorsque vous le reconvertissez en int, il débordera à la valeur correcte.
int
to Hex:
Integer.toHexString(intValue);
Hex à int
:
Integer.valueOf(hexString, 16).intValue();
Vous pouvez également utiliser long
à la place de int
(si la valeur ne correspond pas à la limite int
):
Hex à long
:
Long.valueOf(hexString, 16).longValue()
long
en Hex
Long.toHexString(longValue)
Il est à noter que Java 8 a les méthodes Integer.parseUnsignedInt
Et Long.parseUnsignedLong
Qui font ce que vous vouliez, plus précisément:
Integer.parseUnsignedInt("ffff8000",16) == -32768
Le nom est un peu déroutant, car il analyse un entier signé d'une chaîne hexagonale, mais il fait le travail.
Essayez d'utiliser la classe BigInteger, cela fonctionne.
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());
Comme Integer.toHexString (octet/entier) ne fonctionne pas lorsque vous essayez de convertir des octets signés tels que les caractères décodés UTF-16, vous devez utiliser:
Integer.toString(byte/integer, 16);
ou
String.format("%02X", byte/integer);
inversez vous pouvez utiliser
Integer.parseInt(hexString, 16);
La méthode parseInt de Java est en réalité un groupe de code mangeant "false" hex: si vous voulez traduire -32768, vous devez convertir la valeur absolue en hex, puis ajouter la chaîne avec "-".
Il existe un exemple de fichier Integer.Java:
public static int parseInt(String s, int radix)
La description est assez explicite:
* 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
Utiliser Integer.toHexString(...)
est une bonne réponse. Mais personnellement, préférez utiliser String.format(...)
.
Essayez cet échantillon comme test.
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();
Le code ci-dessous fonctionnerait:
int a=-32768;
String a1=Integer.toHexString(a);
int parsedResult=(int)Long.parseLong(a1,16);
System.out.println("Parsed Value is " +parsedResult);
Héhé, curieux. Je pense que c'est un "bug intentianal", pour ainsi dire.
La raison sous-jacente est la façon dont la classe Integer est écrite. Fondamentalement, parseInt est "optimisé" pour les nombres positifs. Lorsqu'il analyse la chaîne, il génère le résultat de manière cumulative, mais est annulé. Ensuite, il retourne le signe du résultat final.
Exemple:
66 = 0x42
analysé comme:
4*(-1) = -4
-4 * 16 = -64 (hex 4 parsed)
-64 - 2 = -66 (hex 2 parsed)
return -66 * (-1) = 66
Maintenant, regardons votre exemple 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): pour que parseInt () fonctionne de manière "cohérente" pour -Integer.MAX_VALUE <= n <= Integer.MAX_VALUE, il aurait fallu que la logique "réponde" lorsque -Integer.MAX_VALUE soit atteint. résultat cumulatif, en partant de l'extrémité maxi de la plage entière et en descendant vers le bas. Pourquoi ils ne l'ont pas fait, il faudrait d'abord demander à Josh Bloch ou à quiconque de l'avoir mis en œuvre. Cela pourrait simplement être une optimisation.
Cependant,
Hex=Integer.toHexString(Integer.MAX_VALUE);
System.out.println(Hex);
System.out.println(Integer.parseInt(Hex.toUpperCase(), 16));
fonctionne très bien, juste pour cette raison. Vous pouvez trouver ce commentaire dans la source d'Integer.
// Accumulating negatively avoids surprises near MAX_VALUE