繁体   English   中英

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

[英]Unable to parse 64 bit binary numbers to long

给定字符串“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。 我是什么做的?

当你反转零

number = ~number

你得到消极的。 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);
    }
}

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

Long.parseLong(String, int) 

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

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

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

"1111111111111111111111111111111111111111111111111111111111111111";

,我们有:

long res = Long.parseLong(s.substring(1), 2);

res的二进制形式是:

0111111111111111111111111111111111111111111111111111111111111111

现在,如果我们知道s的第一个char'1' ,那么我们执行以下操作:

 res |= (1L << 63);

(1L << 63)产生:

1000000000000000000000000000000000000000000000000000000000000000

因此,对于res的按位或赋值将产生64 1,其中二进制补码为-1,如期望的那样。

这是因为Long.parseLong(以及Integer.parseInt等)无法解析两个补码,因此“111111111111111111111111111111111111111111111111111111111111111”是一个超过Long.MAX_VALUE的正数。 但我们可以使用BigInteger

long l = new BigInteger("1111111111111111111111111111111111111111111111111111111111111111", 2).longValue()

这会产生预期结果= -1

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM