6

Given binary number in a string "0", I converted it to long to find its Bitwise Not/Complement.

long number = Long.parseLong("0",2);
number = ~number;
System.out.println(Long.toBinaryString(number));

which prints

1111111111111111111111111111111111111111111111111111111111111111

i.e., 64 1's. But I'm unable to find complement of this.

Long.parseLong("111111111111111111111111111111111111111111111111111111111111111",2); //fails

I get java.lang.NumberFormatException. What am I to do?

3 Answers 3

7

When you invert zero

number = ~number

you get negative one. The Long.parseLong(String, int) method expects negative numbers to be represented with a minus prefix. When you pass 64 1-s to the method, it thinks it's an overflow, and returns an error.

One way to fix this is to check that the length is less than 64 before you parse the value. If the length is exactly 64, chop off the first digit, and parse the rest of the number. Then check the initial digit. If it is zero, leave the parsed number as is; otherwise, use binary OR to set the most significant bit:

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);
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

You've constantly been about 45 seconds ahead of me. Not going to bother to regurgitate what you've already said in the fix portion. Good answer, +1.
5

The complement of 0 is 64 1's, which is equivalent to -1, since Java uses two's complement.

Long.parseLong(String, int) 

expects a signed long (aka if the number is negative, it expects a leading -), but you are passing it 64 1's, which are supposed to represent -1, but do not in this form.

Given that for negatives, it expects the a negative sign, passing it 64 1's causes the it to believe that the number is too large.

EDIT (explanation of dasblinkenlight's fix: couldn't properly format in comment):
So if String s =

"1111111111111111111111111111111111111111111111111111111111111111";

, and we have:

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

The binary form of res is:

0111111111111111111111111111111111111111111111111111111111111111

Now, if we know that the first char of s is '1', then we do the following:

 res |= (1L << 63);

(1L << 63) produces:

1000000000000000000000000000000000000000000000000000000000000000

So, the bitwise-or assignment to res yields 64 1's, which in two's complement is -1, as desired.

Comments

0

This is because Long.parseLong (as well as Integer.parseInt etc) cannot parse two's complements and for it "111111111111111111111111111111111111111111111111111111111111111" is a positive number that exceeds Long.MAX_VALUE. But we can use BigInteger

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

this produces expected result = -1

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.