Java converting int to hex and back again

前端 未结 10 1042
鱼传尺愫
鱼传尺愫 2020-11-28 08:34

I have the following code...

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

This equates to ffff8000

int         


        
相关标签:
10条回答
  • 2020-11-28 08:46

    It overflows, because the number is negative.

    Try this and it will work:

    int n = (int) Long.parseLong("ffff8000", 16);
    
    0 讨论(0)
  • 2020-11-28 08:47

    Java's parseInt method is actally a bunch of code eating "false" hex : if you want to translate -32768, you should convert the absolute value into hex, then prepend the string with '-'.

    There is a sample of Integer.java file :

    public static int parseInt(String s, int radix)
    

    The description is quite 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
    
    0 讨论(0)
  • 2020-11-28 08:47

    Hehe, curious. I think this is an "intentianal bug", so to speak.

    The underlying reason is how the Integer class is written. Basically, parseInt is "optimized" for positive numbers. When it parses the string, it builds the result cumulatively, but negated. Then it flips the sign of the end-result.

    Example:

    66 = 0x42

    parsed like:

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

    Now, let's 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 the parseInt() to work "consistently" for -Integer.MAX_VALUE <= n <= Integer.MAX_VALUE, they would have had to implement logic to "rotate" when reaching -Integer.MAX_VALUE in the cumulative result, starting over at the max-end of the integer range and continuing downwards from there. Why they did not do this, one would have to ask Josh Bloch or whoever implemented it in the first place. It might just be an optimization.

    However,

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

    works just fine, for just this reason. In the sourcee for Integer you can find this comment.

    // Accumulating negatively avoids surprises near MAX_VALUE
    
    0 讨论(0)
  • 2020-11-28 08:49

    Try using 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());
    
    0 讨论(0)
  • 2020-11-28 08:50

    Using Integer.toHexString(...) is a good answer. But personally 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();
    
    0 讨论(0)
  • 2020-11-28 08:57
    • int to Hex :

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

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

    You may also want to use long instead of int (if the value does not fit the int bounds):

    • Hex to long:

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

      Long.toHexString(longValue)
      
    0 讨论(0)
提交回复
热议问题