Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bitwise negation gives unexpected result

I am trying to write a bitwise calculator in java, something that you could input an expression such as ~101 and it would give back 10 however when i run this code

import java.util.Scanner;

public class Test
{
    public static void main(String[] args)
    {
        Integer a = Integer.valueOf("101", 2);
        System.out.println(Integer.toString(~a,2));
    }
}

it outputs -110 why?

like image 638
Josh Sobel Avatar asked Mar 22 '13 16:03

Josh Sobel


People also ask

How does bitwise negation work?

The ~ (bitwise negation) operator yields the bitwise complement of the operand. In the binary representation of the result, every bit has the opposite value of the same bit in the binary representation of the operand. The operand must have an integral type.

Can result of bitwise and be negative?

The result of bitwise-AND can be negative, e.g. (-1) & (-1) is definitely -1 . However, if either operand is nonnegative, the result must also be nonnegative. This is because in 2's complement representation, a negative number must have its 31st bit set, and a nonnegative number must have its 31st bit cleared.

Why is bitwise not negative?

Whether an integer is positive or negative (the sign of the integer) is stored in a dedicated bit, the sign bit. The bitwise NOT affects this bit, too, so any positive number becomes a negative number and vice versa.

What is a bitwise inversion?

In telecommunications, bit inversion means the changing of the state of a bit to the opposite state, i.e. the changing of a 0 bit to 1 or of a 1 bit to 0. It also refers to the changing of a state representing a given bit to the opposite state.


1 Answers

You are assuming that 101 is three bits long. Java doesn't support variable length bit operations, it operates on a whole int of bits, so ~ will be the not of a 32 bit long "101".

--- Edited after being asked "How can I fix this?" ---

That's a really good question, but the answer is a mix of "you can't" and "you can achieve the same thing by different means".

You can't fix the ~ operator, as it does what it does. It would sort of be like asking to fix + to only add the 1's place. Just not going to happen.

You can achieve the desired operation, but you need a bit more "stuff" to get it going. First you must have something (another int) that specifies the bits of interest. This is typically called a bit mask.

 int mask = 0x00000007; // just the last 3 bits.

 int masked_inverse = (~value) & mask;

Note that what we did was really invert 32 bits, then zeroed out 29 of those bits; because, they were set to zero in the mask, which means "we don't care about them". This can also be imagined as leveraging the & operator such that we say "if set and we care about it, set it".

Now you will still have 32 bits, but only the lower 3 will be inverted. If you want a 3 bit data structure, then that's a different story. Java (and most languages) just don't support such things directly. So, you might be tempted to add another type to Java to support that. Java adds types via a class mechanism, but the built-in types are not changeable. This means you could write a class to represent a 3 bit data structure, but it will have to handle ints internally as 32 bit fields.

Fortunately for you, someone has already done this. It is part of the standard Java library, and is called a BitSet.

BitSet threeBits = new BitSet(3);
threeBits.set(2);  // set bit index 2
threeBits.set(0);  // set bit index 0
threeBits.flip(0,3);

However, such bit manipulations have a different feel to them due to the constraints of the Class / Object system in Java, which follows from defining classes as the only way to add new types in Java.

like image 104
Edwin Buck Avatar answered Oct 05 '22 16:10

Edwin Buck