Java converts int to hex and vice versa

I have the following code ...

int Val=-32768; String Hex=Integer.toHexString(Val); 

This corresponds to ffff8000

 int FirstAttempt=Integer.parseInt(Hex,16); // Error "Invalid Int" int SecondAttempt=Integer.decode("0x"+Hex); // Error "Invalid Int" 

So, it initially converts the value -32768 to the sixth line of ffff8000, but then it cannot convert the hexadecimal string to Integer.

In .Net it works as I expected, and returns -32768 .

I know that I could write my own little method to convert it myself, but I'm just wondering if I am missing something or if it really is a mistake?

+45
java string hex
Aug 17 2018-12-12T00:
source share
9 answers

It overflows because the number is negative.

Try this and it will work:

 int n = (int) Long.parseLong("ffff8000", 16); 
+34
Aug 17 '12 at 12:12
source share
 int val = -32768; String hex = Integer.toHexString(val); int parsedResult = (int) Long.parseLong(hex, 16); System.out.println(parsedResult); 

How can you do this.

The reason this won't work: Integer.parseInt accepts a signed int, and toHexString produces an unsigned result. Therefore, if you insert something larger than 0x7FFFFFF , the error will be automatically thrown. If you parse it as long , it will still be signed. But when you return it back to int, it will overflow to the correct value.

+47
Aug 17 '12 at 12:12
source share
  • int in Hex:

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

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

You can also use long instead of int (if the value does not match the bounds of int ):

  • Hex to long :

     Long.valueOf(hexString, 16).longValue() 
  • long to hex

     Long.toHexString(longValue) 
+16
Aug 17 '12 at 12:10
source share

Try using the BigInteger class, it works.

 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()); 
+6
Aug 17 '12 at 12:16
source share

It is worth noting that Java 8 has the Integer.parseUnsignedInt and Long.parseUnsignedLong methods that do what you wanted, in particular:

Integer.parseUnsignedInt("ffff8000",16) == -32768

The name is a bit confusing as it parses a signed integer from a hexadecimal string, but it does the job.

+6
Mar 04 '16 at 19:09
source share

You should know that the Java parseInt method is a bunch of code that has a "false" hex: if you want to translate -32768, you must convert the absolute value to hexadecimal, and then add the line with "-".

There is a sample Integer.java file:

 public static int parseInt(String s, int radix) 

The description is pretty explicit:

 * 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 
+2
Aug 17 '12 at 12:16
source share

Hehe, curious. I think this is a “deliberate mistake”, so to speak.

The main reason is how the Integer class is written. Basically, parseInt is "optimized" for positive numbers. When he parses the string, he creates the result cumulatively, but is denied. Then he flips the mark of the end result.

Example:

66 = 0x42

understands how:

 4*(-1) = -4 -4 * 16 = -64 (hex 4 parsed) -64 - 2 = -66 (hex 2 parsed) return -66 * (-1) = 66 

Now look at your example 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): in order for parseInt () to work "sequentially" for -Integer.MAX_VALUE <= n <= Integer.MAX_VALUE, they would have to implement the logic for "rotation" when they reach - Integer.MAX_VALUE in the cumulative result, starting from the maximum end of the integer range and continuing down from there. Why they did not, it would be necessary to ask Josh Bloch or whoever implemented it in the first place. It could just be an optimization.

However

 Hex=Integer.toHexString(Integer.MAX_VALUE); System.out.println(Hex); System.out.println(Integer.parseInt(Hex.toUpperCase(), 16)); 

It works just fine, for this very reason. In the source for Integer you can find this comment.

 // Accumulating negatively avoids surprises near MAX_VALUE 
+1
Aug 17 '12 at 13:01
source share

Using Integer.toHexString(...) is a good answer. But personally, we prefer to use String.format(...) .

Try this sample as a 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(); 
+1
Feb 09 '17 at 17:25
source share

How Integer.toHexString (byte / integer) does not work when you try to convert signed bytes, such as UTF-16 decoded characters, which you should use:

 Integer.toString(byte/integer, 16); 

or

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

back you can use

 Integer.parseInt(hexString, 16); 
0
Jun 06 '17 at 11:44 on
source share



All Articles