【问题标题】:Java converting int to hex and back againJava将int转换为十六进制并再次转换回来
【发布时间】:2021-02-25 10:53:21
【问题描述】:

我有以下代码...

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

这相当于ffff8000

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

因此,最初,它将值 -32768 转换为十六进制字符串 ffff8000,但随后无法将十六进制字符串转换回整数。

.Net 中,它按我的预期工作,returns -32768

我知道我可以编写自己的小方法来自己转换它,但我只是想知道我是否遗漏了什么,或者这是否真的是一个错误?

【问题讨论】:

标签: java string hex


【解决方案1】:
int val = -32768;
String hex = Integer.toHexString(val);

int parsedResult = (int) Long.parseLong(hex, 16);
System.out.println(parsedResult);

这就是你可以做到的。

它不能按您的方式工作的原因:Integer.parseInt 采用带符号的 int,而 toHexString 产生无符号的结果。所以如果你插入高于0x7FFFFFF的东西,就会自动抛出错误。如果您将其解析为long,它仍然会被签名。但是当你将它转换回 int 时,它会溢出到正确的值。

【讨论】:

    【解决方案2】:

    溢出,因为数字是负数。

    试试这个,它会起作用的:

    int n = (int) Long.parseLong("ffff8000", 16);
    

    【讨论】:

    • 感谢 roni,这似乎是最好的解决方案。尽管 Int.parseInt 没有像我预期的那样工作似乎仍然很奇怪。
    • ffff8000 不适合 int(大于 max int),这是一个正数(它是一个字符串,因此只有当它有减号时才为负数)
    • 这是因为 parseInt 采用有符号整数,而 toHexString 产生无符号结果(见我的回答)...
    • 谢谢你拯救了我的一天:)
    • @roni,如果十六进制是字符串值,如String Hex=Integer.toHexString("xyz"); 如何从十六进制取回字符串为“xyz”
    【解决方案3】:
    • int 转十六进制:

      Integer.toHexString(intValue);
      
    • 十六进制到int

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

    您可能还想使用long 而不是int(如果该值不符合int 界限):

    • 十六进制到long:

      Long.valueOf(hexString, 16).longValue()
      
    • long 转十六进制

      Long.toHexString(longValue)
      

    【讨论】:

      【解决方案4】:

      值得一提的是,Java 8 有 Integer.parseUnsignedIntLong.parseUnsignedLong 方法可以满足您的需求,具体来说:

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

      这个名字有点令人困惑,因为它从一个十六进制字符串中解析一个有符号整数,但它确实有效。

      【讨论】:

        【解决方案5】:

        尝试使用 BigInteger 类,它可以工作。

        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】:

          由于 Integer.toHexString(byte/integer) 在您尝试转换有符号字节(如您必须使用的 UTF-16 解码字符)时不起作用:

          Integer.toString(byte/integer, 16);
          

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

          你可以使用反向

          Integer.parseInt(hexString, 16);
          

          【讨论】:

            【解决方案7】:

            Java 的 parseInt 方法实际上是一堆吃“假”十六进制的代码:如果要翻译 -32768,则应将绝对值转换为十六进制,然后在字符串前面加上“-”。

            有一个 Integer.java 文件的样本:

            public static int parseInt(String s, int radix)
            

            描述很明确:

            * 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
            

            【讨论】:

              【解决方案8】:

              使用Integer.toHexString(...) 是一个很好的答案。不过个人更喜欢用String.format(...)

              试试这个样本作为测试。

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

              【讨论】:

                【解决方案9】:

                下面的代码可以工作:

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

                【讨论】:

                  【解决方案10】:

                  呵呵,好奇。我认为这是一个“故意的错误”,可以这么说。

                  根本原因是 Integer 类的编写方式。基本上, parseInt 针对正数进行了“优化”。当它解析字符串时,它会累积地构建结果,但会被否定。然后它翻转最终结果的符号。

                  例子:

                  66 = 0x42

                  解析如下:

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

                  现在,让我们看看您的示例 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.
                  

                  编辑(添加):为了使 parseInt() 能够“始终如一地”为 -Integer.MAX_VALUE

                  然而,

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

                  工作得很好,正是因为这个原因。在 Integer 的源代码中,您可以找到此评论。

                  // Accumulating negatively avoids surprises near MAX_VALUE
                  

                  【讨论】:

                  • // Accumulating negatively avoids surprises near MAX_VALUE -> 但它引入了惊喜低于 0 ^^
                  猜你喜欢
                  • 2021-12-17
                  • 2012-04-21
                  • 1970-01-01
                  • 1970-01-01
                  • 2015-10-07
                  • 2014-12-15
                  相关资源
                  最近更新 更多