如何在Java中将一个64位二进制字符串转换为长整型?

12

我想将一个64位宽的二进制字符串转换成长整型,有一个静态方法:

Long.parseLong(String s, int radix)

我希望做这个,但不适用于我的情况。

问题在于我的二进制字符串是一个机器风格的长整数。

例如:

1111111111111111111111111111111111111111111111111111111110000101 代表着-123,但是这种方法将其识别为一个巨大的正数,这使我很困扰,我该如何解决这个问题呢?

我必须编写一个补码函数吗?


2
请问您能否更详细地解释一下“机器风格长整型”以及123如何用这种长二进制表示法表示。因为123的二进制是1111011。如果我没有理解您的问题,请见谅。 - M S
首先,非常感谢。它是-123而不是123,也就是负数。机器风格意味着它是计算机硬件的表示方式,使用第一位上的“1”表示负数,使用“0”表示非正数,这与人类风格不同,人类风格使用“-”表示负数。我说得清楚吗? - Sefier Tang
我认为你可能需要再次检查将-123表示为长整数的字符串。 Long.toString(-123,2)产生 -1111011 - buruzaemon
5个回答

15

你可以使用 BigInteger

public static void main(String... args) {
    String s = "1111111111111111111111111111111111111111111111111111111110000101";
    long l = parseLong(s, 2);
    System.out.println(s +" => " + l);

    String s2 = s.substring(1);
    long l2 = parseLong(s2, 2);
    System.out.println(s2 +" => " + l2);
}

private static long parseLong(String s, int base) {
    return new BigInteger(s, base).longValue();
}
打印
1111111111111111111111111111111111111111111111111111111110000101 => -123
111111111111111111111111111111111111111111111111111111110000101 => 9223372036854775685

2

我用拼凑的方法实现了一个解决方案,仅在您的情况下进行了测试:

public static long makeLong(String input) {
    if(input.substring(0,1).equals("1")) {
        return -1 * (Long.MAX_VALUE - Long.parseLong(input.substring(1), 2) + 1);
    } else {
        return Long.parseLong(input, 2);
    }
}

基本上,如果第一个位是1,那么这个数字是负数,所以我们将其余部分解析为正数,然后通过从Long.MAX_VALUE中减去该结果并加一些二进制补码魔术,再将负数强制返回到数字中来。否则,应用正常的转换。


第一个返回语句可以替换为 return Long.parseLong(input.substring(1), 2) + Long.MIN_VALUE - x22
正如布什总统所说,“太棒了”!这个网站、这些答案和这些人都很棒。我最喜欢这个答案,但还是要感谢大家的回复。 - Sefier Tang
1
只有当数字长度为64位时才有效。如果它没有前导零,那么第一个数字很可能是1 - Peter Lawrey
public static long makeLong(String input) { return Long.parseUnsignedLong(input, 2); } 这段代码也可以解决问题。 - Maxim Bjjtwins

2
你可以自己设置这些位...
assert string.length() == 64;
long result = 0;
for (int i = 0; i < 64; ++i) {
    char c = string.charAt(63-i);
    switch (c) {
        case '1': result |= (1L << i); break;
        case '0'; break;
        default: throw new WhateverException("bad char " + c);
    }
}

编辑:我最初使用的是1 << i,这意味着移位是作为int类型进行的。已修复为作为long类型进行移位。


0

我认为没有一个库函数可以做到你想要的,但是这个方法应该可以:

long num = 0L;
for (int i = 0; i < 64; i++) {
    if (yourString.charAt(i) == '1') {
        num ^= 1L << (63 - i);
    }
}

当然,您应该检查确保字符串长度为64且仅包含0和1。

0

我认为最简单的方法是使用Long.parseUnsignedLong,例如:

String str = "1111111111111111111111111111111111111111111111111111111110000101";
System.out.println(Long.parseUnsignedLong(str, 2));

将打印:
-123

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接