2012-08-17 65 views
48

我有以下代码...的Java转换INT为十六进制,然后再返回

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

我知道我可以自己编写自己的小方法来转换它,但我只是想知道我是否错过了某些东西,或者如果这真的是一个错误?

+1

可能都plicate [Java负int到十六进制失败](http:// stackoverflow。com/questions/845230/java-negative-int-to-hex-and-back-failures) – 2012-08-17 12:17:38

+4

只是一个提示:由于约定变量名称以小写字母开头:'in​​t firstAttempt = 5;' – Simulant 2012-08-17 12:20:24

回答

34

它溢出,因为数字是负数。

试试这个,它会工作:

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

Thanks roni,that似乎是最好的解决方案。尽管Int.parseInt不能像我所期望的那样工作,但它仍然显得很古怪。 – 2012-08-17 12:36:20

+0

ffff8000不适合int(大于max int),这是一个正数(它是一个字符串,所以它只在负值时才是负数) – roni 2012-08-17 12:40:51

+1

这是因为parseInt使用带符号的整数并且toHexString产生一个无符号的结果(看到我的回答)... – brimborium 2012-08-17 12:41:46

16
  • int为十六进制:

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

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

您可能还需要使用long代替int(如果该值不适合int范围):

  • 十六进制long

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

    Long.toHexString(longValue) 
    
48
int val = -32768; 
String hex = Integer.toHexString(val); 

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

这就是你如何能做到这一点。

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

6

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

你应该知道,Java的parseInt函数的方法是actally的代码吃“假”六角一串:如果你想翻译-32768,你应该绝对值转换为十六进制,然后前面加上'字符串 - ”。

有一个Integer样本。Java文件:

​​

的描述是相当明确的:

* 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 
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

'//累积消极地避免了MAX_VALUE附近的惊喜 - >但它引入了惊人的降低0 ^^ – brimborium 2012-08-17 13:07:17

6

值得一提的是,Java的8所拥有的方法Integer.parseUnsignedIntLong.parseUnsignedLong已经做了你想要的东西,具体是:

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

名字是有点混乱,因为它分析从一个有符号整数一个十六进制字符串,但它的工作。

1

使用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

由于Integer.toHexString(字节/整数),当你试图符号字节转换像UTF-16解码后的字符不工作,你必须使用:

Integer.toString(byte/integer, 16); 

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

反向您可以使用

Integer.parseInt(hexString, 16); 
相关问题