如何将 "unsigned" long 转换为 BigInteger
How to convert an "unsigned" long to BigInteger
如果我有一个 Java long
值 - 比如 x
- 应该被解释为无符号值(即 0x8000_0000_0000_0000
和更高的值应该被解释为正数值) 那么如何将其转换为 BigInteger
?
显然,BigInteger.valueOf(x)
会得到负值,转换为十六进制或字节似乎很浪费。
实际上,转换非常简单。您可以使用类似于将无符号整数转换为长整数的掩码:
让我们首先将掩码创建为常量(这只会导致最低有效的 32 位设置为 1):
private static final long UNSIGNED_INT_MASK = (1L << Integer.SIZE) - 1L;
然后我们可以执行:
int unsignedInt = 0x8000_0000; // sample input value
long l = (long) unsignedInt & UNSIGNED_INT_MASK;
所以对于 BigInteger
我们可以像这样创建掩码(64 个最低有效位设置为 1):
// use "import static java.math.BigInteger.ONE;" to shorten this line
private static final BigInteger UNSIGNED_LONG_MASK = BigInteger.ONE.shiftLeft(Long.SIZE).subtract(BigInteger.ONE);
很好,剩下的就简单了:
long unsignedLong = 0x8000_0000_0000_0000L; // sample input value
BigInteger bi = BigInteger.valueOf(unsignedLong).and(UNSIGNED_LONG_MASK);
这不是火箭科学,但有时您只是想找到一个快速简单的答案。
这种转换实际上是在 OpenJDK 的 java.lang.Long
中实现的:Long.java:241。虽然它是私人的,所以将它粘贴在这里:
/**
* Return a BigInteger equal to the unsigned value of the
* argument.
*/
private static BigInteger toUnsignedBigInteger(long i) {
if (i >= 0L)
return BigInteger.valueOf(i);
else {
int upper = (int) (i >>> 32);
int lower = (int) i;
// return (upper << 32) + lower
return (BigInteger.valueOf(Integer.toUnsignedLong(upper))).shiftLeft(32).
add(BigInteger.valueOf(Integer.toUnsignedLong(lower)));
}
}
我的博客上提供了一篇关于未签名 long
和替代品的详尽文章:Unsigned long in Java
如果我有一个 Java long
值 - 比如 x
- 应该被解释为无符号值(即 0x8000_0000_0000_0000
和更高的值应该被解释为正数值) 那么如何将其转换为 BigInteger
?
显然,BigInteger.valueOf(x)
会得到负值,转换为十六进制或字节似乎很浪费。
实际上,转换非常简单。您可以使用类似于将无符号整数转换为长整数的掩码:
让我们首先将掩码创建为常量(这只会导致最低有效的 32 位设置为 1):
private static final long UNSIGNED_INT_MASK = (1L << Integer.SIZE) - 1L;
然后我们可以执行:
int unsignedInt = 0x8000_0000; // sample input value
long l = (long) unsignedInt & UNSIGNED_INT_MASK;
所以对于 BigInteger
我们可以像这样创建掩码(64 个最低有效位设置为 1):
// use "import static java.math.BigInteger.ONE;" to shorten this line
private static final BigInteger UNSIGNED_LONG_MASK = BigInteger.ONE.shiftLeft(Long.SIZE).subtract(BigInteger.ONE);
很好,剩下的就简单了:
long unsignedLong = 0x8000_0000_0000_0000L; // sample input value
BigInteger bi = BigInteger.valueOf(unsignedLong).and(UNSIGNED_LONG_MASK);
这不是火箭科学,但有时您只是想找到一个快速简单的答案。
这种转换实际上是在 OpenJDK 的 java.lang.Long
中实现的:Long.java:241。虽然它是私人的,所以将它粘贴在这里:
/**
* Return a BigInteger equal to the unsigned value of the
* argument.
*/
private static BigInteger toUnsignedBigInteger(long i) {
if (i >= 0L)
return BigInteger.valueOf(i);
else {
int upper = (int) (i >>> 32);
int lower = (int) i;
// return (upper << 32) + lower
return (BigInteger.valueOf(Integer.toUnsignedLong(upper))).shiftLeft(32).
add(BigInteger.valueOf(Integer.toUnsignedLong(lower)));
}
}
我的博客上提供了一篇关于未签名 long
和替代品的详尽文章:Unsigned long in Java