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

Fro*_*yon 5 java binary bit long-integer

给定字符串"0"中的二进制数,我将其转换为long以找到其按位不/补.

long number = Long.parseLong("0",2);
number = ~number;
System.out.println(Long.toBinaryString(number));
Run Code Online (Sandbox Code Playgroud)

打印

1111111111111111111111111111111111111111111111111111111111111111

即64 1.但我无法找到这个的补充.

Long.parseLong("111111111111111111111111111111111111111111111111111111111111111",2); //fails
Run Code Online (Sandbox Code Playgroud)

我得到java.lang.NumberFormatException.我是什么做的?

das*_*ght 7

当你反转零

number = ~number
Run Code Online (Sandbox Code Playgroud)

你得到消极的.该Long.parseLong(String, int)方法期望负数用减去前缀表示.当您将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);
    }
}
Run Code Online (Sandbox Code Playgroud)


Ste*_* P. 5

0的补码是64 1,相当于-1,因为Java使用了两个补码.

Long.parseLong(String, int) 
Run Code Online (Sandbox Code Playgroud)

期望一个有符号长(也就是说,如果数字是负数,它期望一个领先-),但你传递64 1,它应该代表-1,但不是这种形式.

鉴于对于负数,它预期为负号,将其传递给64 1会导致它认为数字太大.

编辑(对dasblinkenlight修复的解释:无法在评论中正确格式化):
所以如果String s =

"1111111111111111111111111111111111111111111111111111111111111111";
Run Code Online (Sandbox Code Playgroud)

,我们有:

long res = Long.parseLong(s.substring(1), 2);
Run Code Online (Sandbox Code Playgroud)

二进制形式res是:

0111111111111111111111111111111111111111111111111111111111111111
Run Code Online (Sandbox Code Playgroud)

现在,如果我们知道第一个chars就是'1',我们做到以下几点:

 res |= (1L << 63);
Run Code Online (Sandbox Code Playgroud)

(1L << 63) 生产:

1000000000000000000000000000000000000000000000000000000000000000
Run Code Online (Sandbox Code Playgroud)

因此,根据需要,按位或赋值res产生64 1,其中2的补码为-1.