Java将int转换为十六进制然后再次返回


80

我有以下代码...

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,但是随后无法将十六进制字符串转换回Integer。

.Net如我所料,它在其中工作,并且returns -32768

我知道我可以编写自己的小方法自己进行转换,但是我只是想知道我是否丢失了某些东西,或者这是否真的是错误?



5
只是一个提示:约定变量名称以小写字母开头:int firstAttempt = 5;
Simulant 2012年

Answers:


48

它溢出,因为数字为负。

试试这个,它将起作用:

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

感谢roni,这似乎是最好的解决方案。尽管Int.parseInt不能按我期望的那样工作仍然很奇怪。
Rich S

ffff8000不适合int(大于max int),这是一个正数(它是一个字符串,因此只有当它为负数时才是负数)
roni bar yanai 2012年

1
这是因为parseInt需要一个带符号的int,而toHexString会产生一个不带符号的结果(请参见我的回答)...
brimborium

谢谢您保存了我的一天:)
Vineesh TP 2015年

1
@roni,如果十六进制具有字符串值,例如String Hex=Integer.toHexString("xyz");如何从十六进制取回字符串作为“ xyz”
怎么办

73
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时,它将溢出到正确的值。


26
  • int 到十六进制:

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

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

您可能还想使用long代替int(如果该值不适合int边界):

  • 十六进制为long

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

    Long.toHexString(longValue)
    

9

值得一提的是,Java 8具有这些方法Integer.parseUnsignedInt并且Long.parseUnsignedLong可以满足您的要求,特别是:

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

这个名称有点令人困惑,因为它从十六进制字符串中解析一个带符号的整数,但是它可以完成工作。


7

尝试使用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());

4

由于在尝试转换带符号的字节(如UTF-16解码字符)时,Integer.toHexString(byte / integer)无法正常工作,因此必须使用:

Integer.toString(byte/integer, 16);

要么

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

可以使用反向

Integer.parseInt(hexString, 16);

3

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

2

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

2

下面的代码可以工作:

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

1

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

根本原因是如何编写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 <= n <= Integer.MAX_VALUE“一致”地工作,当它们到达-Integer.MAX_VALUE时,它们将必须实现“旋转”的逻辑。累积结果,从整数范围的最大值开始,然后从该范围继续向下。为什么他们不这样做,则必须问Josh Bloch或首先实施此方法的人。这可能只是一种优化。

然而,

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

2
// Accumulating negatively avoids surprises near MAX_VALUE->但它引入了更低的惊喜0 ^^
brimborium'Aug
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.