无法将64位二进制数解析为long

时间:2013-08-11 15:50:32

标签: java binary long-integer bit

给定字符串“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。我该怎么办?

3 个答案:

答案 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