int FirstAttempt=Integer.parseInt(Hex,16); // Error "Invalid Int"
int SecondAttempt=Integer.decode("0x"+Hex); // Error "Invalid Int"
所以,一开始,它把数值-32768转换为十六进制字符串fff8000,但随后它不能把十六进制字符串再转换为整数。
在.Net
中,它像我所期望的那样工作,而returns -32768
。
我知道我可以自己写一个小方法来转换,但我只是想知道我是否错过了什么,或者这真的是一个错误?
10 个回答
0 人赞同
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时,它将溢出到正确的值。
0 人赞同
它溢出了,因为这个数字是负数。
试试这个,会有效果的。
int n = (int) Long.parseLong("ffff8000", 16);
0 人赞同
int
to Hex :
Integer.toHexString(intValue);
Hex to int
:
Integer.valueOf(hexString, 16).intValue();
你也可能想使用long
而不是int
(如果数值不符合int
的界限)。
Hex to long
:
Long.valueOf(hexString, 16).longValue()
long
to Hex
Long.toHexString(longValue)
0 人赞同
值得一提的是,Java 8有Integer.parseUnsignedInt
和Long.parseUnsignedLong
的方法,专门做你想要的事情。
Integer.parseUnsignedInt("ffff8000",16) == -32768
这个名字有点令人困惑,因为它从一个十六进制字符串中解析出一个有符号的整数,但它做了这个工作。
0 人赞同
试试使用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());
0 人赞同
由于Integer.toHexString(byte/integer)在你试图转换像UTF-16解码的字符那样的有符号的字节时是不起作用的,你必须使用。
Integer.toString(byte/integer, 16);
String.format("%02X", byte/integer);
反之,你可以使用
Integer.parseInt(hexString, 16);
0 人赞同
Java的parseInt方法实际上是一堆吃 "假 "十六进制的代码:如果你想翻译-32768,你应该把绝对值转换成十六进制,然后在字符串前面加上'-'。
这里有一个Integer.java文件的样本。
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 人赞同
使用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();
0 人赞同
Below code would work:
int a=-32768;
String a1=Integer.toHexString(a);
int parsedResult=(int)Long.parseLong(a1,16);
System.out.println("Parsed Value is " +parsedResult);
0 人赞同
嘿嘿,很好奇。我想这是一个 "故意的错误",可以这么说。
其根本原因在于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.
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));