85 votes

Java convertit les int en hex et inversement

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, dans un premier temps, il convertit la valeur -32768 en une chaîne hexagonale ffff8000, mais il ne parvient pas à reconvertir la chaîne hexagonale en un nombre entier.

En .Net il fonctionne comme je m'y attendais, et returns -32768 .

Je sais que je pourrais écrire ma propre petite méthode pour convertir cela moi-même, mais je me demande si j'ai raté quelque chose, ou s'il s'agit vraiment d'un bogue ?

6voto

Code.IT Points 1075

Integer.toHexString(byte/integer) ne fonctionne pas lorsque vous essayez de convertir des octets signés comme des caractères décodés UTF-16 :

Integer.toString(byte/integer, 16);

ou

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

inversée, vous pouvez utiliser

Integer.parseInt(hexString, 16);

3voto

Benj Points 477

La méthode parseInt de Java est en fait un tas de code qui mange du "faux" hexagone : si vous voulez traduire -32768, vous devez convertir la valeur absolue en hexagone, puis faire précéder la chaîne de "-".

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

2voto

Chef Pharaoh Points 78

Utilisation Integer.toHexString(...) est une bonne réponse. Mais je préfère personnellement utiliser String.format(...) .

Essayez cet échantillon à titre de 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();

2voto

user7258708 Points 191

Le code ci-dessous devrait fonctionner :

int a=-32768;
String a1=Integer.toHexString(a);
int parsedResult=(int)Long.parseLong(a1,16);
System.out.println("Parsed Value is " +parsedResult);

1voto

pap Points 11466

Héhé, curieux. Je pense qu'il s'agit d'un "bug intentionnel", pour ainsi dire.

La raison sous-jacente est la façon dont la classe Integer est écrite. En fait, parseInt est "optimisé" pour les nombres positifs. Lorsqu'il analyse la chaîne de caractères, il construit le résultat de manière cumulative, mais avec une négation. Il inverse ensuite 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

Reprenons maintenant 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.

Édition (ajout) : pour que parseInt() fonctionne de manière "cohérente" pour -Integer.MAX_VALUE <= n <= Integer.MAX_VALUE, il aurait fallu implémenter une logique de "rotation" lorsqu'on atteint -Integer.MAX_VALUE dans le résultat cumulé, en recommençant à l'extrémité maximale de la plage d'entiers et en continuant vers le bas à partir de là. Il faudrait demander à Josh Bloch ou à la personne qui l'a implémenté en premier lieu pourquoi ils n'ont pas fait cela. Il s'agit peut-être simplement d'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, justement pour cette raison. Dans le sourcee pour Integer vous pouvez trouver ce commentaire.

// Accumulating negatively avoids surprises near MAX_VALUE

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X