当我这样做时
Long.parseUnsignedLong("FBD626CC4961A4FC", 16)
我回来了-300009666327239428
这似乎是错误的,因为根据这个答案https://stackoverflow.com/a/2550367/1754020,unsigned long的含义是范围总是正的。
要从此十六进制值中获取正确的数字
BigInteger value = new BigInteger("FBD626CC4961A4FC", 16);
当我打印值时,它会打印正确的值。但如果我做value.longValue()
我再次得到-300009666327239428
这个数字太大而且溢出了吗?
答案 0 :(得分:5)
Java 8(稍微)支持 unsigned longs ,但是,您不能直接打印它们。这样做会给你看到的结果。
如果你有一个未签名的长
Long number = Long.parseUnsignedLong("FBD626CC4961A4FC", 16);
您可以使用函数
获取正确的字符串表示String numberToPrint = Long.toUnsignedString(number);
如果您现在打印numberToPrint
,则
18146734407382312188
更准确地说,您的号码仍然是常规的签名 long
,这就是为什么如果直接打印就会显示溢出的原因。但是,有一些新的静态函数会将值视为无符号,例如此Long.toUnsignedString(long x)
或Long.compareUnsigned(long x, long y)
。
答案 1 :(得分:2)
转换为十进制的十六进制数#include <limits>
#include <iostream>
int main()
{
std::cout << "float\t"
<< std::numeric_limits<float>::lowest() << '\t'
<< std::numeric_limits<float>::max() << '\n';
std::cout << "double\t"
<< std::numeric_limits<double>::lowest() << '\t'
<< std::numeric_limits<double>::max() << '\n';
}
正好是"FBD626CC4961A4FC"
。该数字确实大于最大可能18146734407382312188
,定义为Long.MAX_VALUE
且等于2 63 -1或long
:
9223372036854775807
因此,您回到负数是正常的。
您没有异常,因为Java 8中添加的新System.out.println(new BigInteger("FBD626CC4961A4FC", 16)); // 18146734407382312188
System.out.println(Long.MAX_VALUE); // 9223372036854775807
方法的目的正是为了能够处理无符号长整数(如compareUnsigned
或{{3} })。由于Java divideUnsigned
中的类型*Unsigned*
,这些方法通过将负值理解为大于long
的值来工作:它模拟无符号长整数。 is still unsigned说:
无符号整数将通常与负数关联的值映射到大于
MAX_VALUE
的正数。
如果您打印的MAX_VALUE
是long
的结果,并且它是否定的,则所有这意味着该值大于语言定义的最大长值,但是将unsigned longs作为参数的方法将正确解释这些值,就好像它们大于最大值一样。因此,如果您将该数字传递给parseUnsignedLong
,而不是直接打印,您将获得正确的输出toUnsignedString
。并非所有这些方法都是Java 8的新方法,例如like shown in this other answer也将给定的parseUnsignedLong
解释为基数为16的unsigned long,而打印long
将返回正确的十六进制字符串
toHexString
才会抛出异常sup> 63 -1这是签名长的最大值。
答案 2 :(得分:1)
是的,当您尝试打印时,它会溢出,因为它会转换为Java long
类型。要理解为什么让我们采用你的dec值的log2。
首先,原始值为18146734407382312188
。它的log2是~63.9763437545。
其次,查看documentation:在java中,long类型表示值为-2 ^ 63,最大值为2 ^ 63-1。
所以,你的值明显大于2 ^ 63-1,因此溢出:
-2^63 + (18146734407382312188 - 2^63 + 1) = -300009666327239428
但正如@Keiwan精彩地提到的那样,您仍然可以使用Long.toUnsignedString(number);
打印正确的值
答案 3 :(得分:1)
内部无符号和带符号的数字以相同的方式表示,即在长的情况下为8字节。区别仅在于&#34;签署&#34;位解释,即如果您在C / C ++程序中执行相同操作并将值存储到uint64_t
然后将其转换/映射到asigned int64_t
,您应该得到相同的结果。
由于8字节或64位可以容纳的最大值是2 ^ 64-1,因此这些数字的硬约束。 Java也不直接支持无符号数,因此在long
中存储无符号长整数的唯一方法是允许一个比签名Long.MAX_VALUE
更高的值。事实上,Java并不知道您正在阅读的字符串/十六进制代码是否代表有符号或无符号长整数,因此您可以通过转换回字符串来提供该解释。或使用更大的数据类型,例如BigInteger
。