Java将int转换为hex,然后再返回
我有以下代码…
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转换成一个hexstringffff8000,但它不能将hexstring转换回整数。
在.Net
它按照我的预期工作,并returns -32768
。
我知道我自己可以自己编写一些小的方法来转换,但是我只是想知道我是否错过了一些东西,或者这真的是一个错误?
它溢出,因为这个数字是负数。
试试这个,它会工作:
int n = (int) Long.parseLong("ffff8000", 16);
int val = -32768; String hex = Integer.toHexString(val); int parsedResult = (int) Long.parseLong(hex, 16); System.out.println(parsedResult);
这就是你如何做到的。
之所以没有按照你的方式工作: Integer.parseInt
需要一个带符号的int,而toHexString
会产生一个无符号的结果。 所以如果你插入高于0x7FFFFFF
东西,就会自动抛出一个错误。 如果你parsing它,但是它仍然会被签名。 但是当你把它转换回int时,它会溢出到正确的值。
-
int
到hex:Integer.toHexString(intValue);
-
hex到
int
:Integer.valueOf(hexString, 16).intValue();
你可能也想使用long
而不是int
(如果该值不符合int
范围):
-
hex为
long
:Long.valueOf(hexString, 16).longValue()
-
long
到hexLong.toHexString(longValue)
尝试使用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());
值得一提的是,Java 8拥有Integer.parseUnsignedInt
和Long.parseUnsignedLong
方法,可以完成您想要的function,具体如下:
Integer.parseUnsignedInt("ffff8000",16) == -32768
这个名字有点令人困惑,因为它从一个hexstring中parsing了一个有符号的整数,但是它完成了工作。
你应该知道,Java的parseInt方法实际上是一堆吃“假”hex的代码:如果你想翻译-32768,你应该把绝对值转换成hex,然后用“ – ”作为前缀。
有一个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
呵呵,好奇。 我认为这是一个“天真的错误”,可以这么说。
其根本原因在于如何编写Integer类。 基本上,parseInt是正数的“优化”。 当它parsingstring时,它累积地build立结果,但是否定。 然后翻转最终结果的标志。
例:
66 = 0x42
parsing如下:
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的源代码中你可以find这个评论。
// Accumulating negatively avoids surprises near MAX_VALUE
使用Integer.toHexString(...)
是一个很好的答案。 但个人喜欢使用String.format(...)
。
试试这个样本作为一个testing。
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();
由于Integer.toHexString(字节/整数)在您尝试转换签名字节(如UTF-16解码字符)时无法使用:
Integer.toString(byte/integer, 16);
要么
String.format("%02X", byte/integer);
反向可以使用
Integer.parseInt(hexString, 16);