我正在尝试将十六进制转换为Big Integer。基本上我有32个字符= 16个字节,所以我希望BigInteger
也有16个字节,但在某些情况下,即十六进制从99开始..它生成0的附加字节。我用
new BigInteger(hex, 16)
如何避免第17个字节?
答案 0 :(得分:2)
不可变的任意精度整数。所有操作都表现得好像 BigIntegers用二进制补码表示(如Java的 原始整数类型)。
description of the constructor you are using:
转换指定的BigInteger的String表示形式 基数为BigInteger。字符串表示由一个 可选的减号或加号后跟一个或多个序列 指定基数中的数字。字符到数字的映射是 由Character.digit提供。字符串可能不包含任何无关的内容 字符(例如空格)。
这意味着如果你用new BigInteger( "99000000000000000000000000000000", 16)
调用它,你将得到一个BigInteger,它保存该值(这是一个正值),好像它用二进制补码表示法表示一样。二进制补码中的正值不适合16个字节,因此当然最终结果是17个字节长。
如果你用一个值(两者都包括在内)之间调用它,你可以保证获得一个最大16字节的BigInteger:
- new BigInteger( "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 16)
- new BigInteger("-80000000000000000000000000000000", 16)
任何高于第一个值或低于最后一个值的值将导致超过16个字节。
答案 1 :(得分:1)
第一个字节不能以1
位开头,因为这意味着一个负数。它们通过在数组的开头添加额外的零字节来防止这种情况。该函数将检查并切断该字节:
public static byte[] signedToUnsignedBytes(byte[] myBytes) {
return myBytes.length > 1 && myBytes[0] == 0
? Arrays.copyOfRange(myBytes, 1, myBytes.length)
: myBytes;
}
答案 2 :(得分:0)
超过127的字节值无法用Java byte
表示,因为它们已经签名(好吧,它们可以但Java会将它们视为负数)。
当BigInteger
将值转换为字节数组时,它会在前面添加一个0字节,以区分正值和负值。
这导致128
将变为[0][-128]
,而-128
将变为[-128]
。
如果您打算将结果字节存储为无符号的128位值,则可以切断数组的第一个元素,例如: byte[] sanitizedBytes = Arrays.copyOfRange(myBytes, 1, 16);
。
答案 3 :(得分:0)
似乎您使用BigInteger
仅用于将固定长度的十六进制字符串转换为byte[]
数组。这可以通过其他方式完成,例如,使用ByteBuffer
类:
static byte[] toByteArray(String s) {
ByteBuffer bb = ByteBuffer.allocate(16);
bb.asIntBuffer().put((int) Long.parseLong(s.substring(0, 8), 16))
.put((int) Long.parseLong(s.substring(8, 16), 16))
.put((int) Long.parseLong(s.substring(16, 24), 16))
.put((int) Long.parseLong(s.substring(24), 16));
return bb.array();
}
使用Long.parseUnsignedLong()
:
static byte[] toByteArray8(String s) {
ByteBuffer bb = ByteBuffer.allocate(16);
bb.asLongBuffer().put(Long.parseUnsignedLong(s.substring(0, 16), 16))
.put(Long.parseUnsignedLong(s.substring(16), 16));
return bb.array();
}
这样你就不应该关心极端情况(即使对于"000...000"
字符串也总是会得到16个字节)并且可能会有更少的堆分配。样品用法:
System.out.println(Arrays.toString(toByteArray("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")));
// [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]
System.out.println(Arrays.toString(toByteArray("80000000000000000000000000000000")));
// [-128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
System.out.println(Arrays.toString(toByteArray("123FFFFFFFFFFFFFFFFFFFFFFFFFFFFF")));
// [18, 63, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]
System.out.println(Arrays.toString(toByteArray("007FFFFFFFFFFFFFFFFFFFFFFFFFFFFF")));
// [0, 127, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]
System.out.println(Arrays.toString(toByteArray("00000000000000000000000000000001")));
// [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]