给定字符串“0”中的二进制数,我将其转换为 long 以找到其按位不/补。
long number = Long.parseLong("0",2);
number = ~number;
System.out.println(Long.toBinaryString(number));
打印
1111111111111111111111111111111111111111111111111111111111111111
即64 1。但我无法找到补充。
Long.parseLong("111111111111111111111111111111111111111111111111111111111111111",2); //fails
我得到了java.lang.NumberFormatException。我该怎么办?
答案 0 :(得分:7)
当你反转零
number = ~number
你得到消极的一面。 Long.parseLong(String, int)
方法expects negative numbers to be represented with a minus prefix。当你将64个1-s传递给方法时,它会认为它是溢出的,并返回错误。
解决此问题的一种方法是在解析值之前检查长度是否小于64。如果长度恰好是64,请切掉第一个数字,然后解析数字的其余部分。然后检查初始数字。如果为零,则保留解析后的数字;否则,使用二进制OR
设置最高位:
String s = "1111111111111111111111111111111111111111111111111111111111111111";
long res;
if (s.length() < 64) {
res = Long.parseLong(s, 2);
} else {
res = Long.parseLong(s.substring(1), 2);
if (s.charAt(0) == '1') {
res |= (1L << 63);
}
}
答案 1 :(得分:5)
0的补码是64 1,相当于-1,因为Java使用two's complement。
Long.parseLong(String, int)
预计签名长(如果数字为负数,则需要前导-
),但是你传递的是64 1,它应该代表-1,但是不要这种形式。
鉴于对于负数,它预期为负号,将其传递给64 1会导致它认为数字太大。
编辑(对dasblinkenlight修复的解释:无法在评论中正确格式化):
如果是String s =
"1111111111111111111111111111111111111111111111111111111111111111";
,我们有:
long res = Long.parseLong(s.substring(1), 2);
res
的二进制形式是:
0111111111111111111111111111111111111111111111111111111111111111
现在,如果我们知道char
的第一个s
是'1'
,那么我们会执行以下操作:
res |= (1L << 63);
(1L << 63)
产生:
1000000000000000000000000000000000000000000000000000000000000000
因此,对res
的按位或赋值产生64 1,其中2的补码为-1,如期望的那样。
答案 2 :(得分:0)
这是因为Long.parseLong(以及Integer.parseInt等)无法解析两个补码,因此“111111111111111111111111111111111111111111111111111111111111111”是一个超过Long.MAX_VALUE的正数。但我们可以使用BigInteger
long l = new BigInteger("1111111111111111111111111111111111111111111111111111111111111111", 2).longValue()
这会产生预期结果= -1