java将int转换为hex并再次转换

8e2ybdfx  于 2021-07-09  发布在  Java
关注(0)|答案(10)|浏览(1158)

我有以下代码。。。

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` .
我知道我可以自己编写一个小方法来转换它,但我只是想知道我是否遗漏了什么,或者这是否真的是一个bug?
vbkedwbf

vbkedwbf1#

当您试图转换有符号字节(如必须使用的utf-16解码字符)时,as integer.tohexstring(byte/integer)不起作用:

Integer.toString(byte/integer, 16);

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

你可以用倒过来

Integer.parseInt(hexString, 16);
crcmnpdw

crcmnpdw2#

int 到十六进制:

Integer.toHexString(intValue);

十六进制到 int :

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

您也可以使用 long 而不是 int (如果值不符合 int 界限):
十六进制到 long :

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

Long.toHexString(longValue)

bttbmeg0

bttbmeg03#

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

busg9geu4#

java的parseint方法实际上是一堆吃“false”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
sf6xfgos

sf6xfgos5#

值得一提的是,Java8具有 Integer.parseUnsignedInt 以及 Long.parseUnsignedLong 这就是你想要的,特别是: Integer.parseUnsignedInt("ffff8000",16) == -32768 这个名称有点混乱,因为它从十六进制字符串中解析有符号整数,但它确实起作用。

egmofgnx

egmofgnx6#

它溢出了,因为数字是负数。
试试这个,它会起作用的:

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

t3irkdon7#

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

ztigrdn8

ztigrdn88#

以下代码将起作用:

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

368yc8dk9#

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

mefy6pfw10#

呵呵,好奇。可以说,我认为这是一个“内部缺陷”。
根本原因是整数类是如何编写的。基本上,parseint对正数进行了“优化”。当它解析字符串时,它累积地构建结果,但取反。然后它翻转最终结果的符号。
例子:
66=0x42
解析如下:

4*(-1) = -4
-4 * 16 = -64 (hex 4 parsed)

-64 - 2 = -66 (hex 2 parsed)

return -66 * (-1) = 66

现在,让我们看看您的示例FF8000

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):为了让parseint()对-integer.max\u value<=n<=integer.max\u value“一致地”工作,当累积结果中达到-integer.max\u value时,它们必须实现逻辑来“旋转”,从整数范围的最大端开始,然后从那里继续向下。为什么他们不这样做,人们必须问乔什布洛赫或谁在第一时间实现了它。这可能只是一个优化。
然而,

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

就因为这个原因,一切正常。在integer的sourcee中可以找到此注解。

// Accumulating negatively avoids surprises near MAX_VALUE

相关问题