12

I want to convert a 64-width binary string to long, there is a static method:

Long.parseLong(String s, int radix)

to do this, but it isn't suitable for my case.

The problem is my binary string is a machine-style long int.

For example:

1111111111111111111111111111111111111111111111111111111110000101 represents -123, but this method recognize it as a huge positive number, this troubles me, how could I solve this problem?

Must I write a function that does the complement?

reevesy
  • 3,452
  • 1
  • 26
  • 23
Sefier Tang
  • 770
  • 3
  • 8
  • 25
  • 2
    Could you please explain more on `machine-style long int` and how 123 is represented by that long binary. Coz binary of 123 is 1111011. Sorry if i didnt got your question right. – M S Dec 02 '11 at 06:59
  • First, Thank you very much. It's -123 but not 123, which is negative. machine-style means it's the representation of the hardware of the computer, which use "1" in the first bit to mean negative number, and 0 to mean non-positive number, it's different from human-style, who use "-" for negative number. Am I clear? – Sefier Tang Dec 02 '11 at 07:05
  • I think you might need to double-check your string representation of -123 as a long number. `Long.toString(-123, 2)` yields `-1111011`. – buruzaemon Dec 02 '11 at 07:10

5 Answers5

15

You can use 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();
}

prints

1111111111111111111111111111111111111111111111111111111110000101 => -123
111111111111111111111111111111111111111111111111111111110000101 => 9223372036854775685
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
2

My incredibly hacked-together solution, tested only on your case:

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);
    }
}

Basically, if the first bit is a one, the number is negative, so we parse the rest of the number as a positive, then do some two's complement magic by subtracting that result from Long.MAX_VALUE and adding one, then forcing the negative back onto the number returned. Otherwise, the normal conversion applies.

Tim
  • 59,527
  • 19
  • 156
  • 165
  • First return statement can be replaced with `return Long.parseLong(input.substring(1), 2) + Long.MIN_VALUE`. – x22 Dec 02 '11 at 07:29
  • As President Bush said, "awesome"! Awesome site, awesome answers and awesome guys. I like this answer best but thank you all for your great replies. – Sefier Tang Dec 02 '11 at 07:38
  • 1
    That will only work if the number is 64-digits long. If it has no leading zeros its likely that the first digit will be `1` – Peter Lawrey Dec 02 '11 at 09:31
  • `public static long makeLong(String input) { return Long.parseUnsignedLong(input, 2); }` will do the trick as well – Maxim Bjjtwins Jul 14 '19 at 17:39
2

You could just set the bits yourself...

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);
    }
}

EDIT: I originally had 1 << i, which means the shifting is being done as an int. Fixed to make it being done as a long.

yshavit
  • 42,327
  • 7
  • 87
  • 124
0

I think that the easiest way is to use Long.parseUnsignedLong for example:

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

Will print:

-123
ValeriST
  • 1
  • 3
0

I don't think there's a library function to do what you want, but this should work:

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

Of course, you should check to make sure that the string is length 64 and contains only 0 and 1.

Taymon
  • 24,950
  • 9
  • 62
  • 84