Search code examples
javabit-shiftshorttwos-complementabsolute-value

Java Method returns wrong value after left and right arithmetic bit-shifting


I have a method that looks like this:

private short getAddress(short ir) { //performs bit shifting to isolate and find address
        short addr = ir;
        addr = (short) (addr << 11); //remove leading bits
        if (debug == true) {
            System.out.println("LeftSh Reads " + Integer.toBinaryString(addr));
            debugging();
        }
        addr = (short) Math.abs((addr >> 11)); //Shift back to starting position. Java's casting leaves this in negative for some reason. Taking the absolute value fixes it.
        if (debug == true) {
            System.out.println("RightSh Reads " + Integer.toBinaryString(addr));
            debugging();
        }
        return addr;
    }

For this example, short ir = 1557.

The expected return value for addr is 21, but I'm getting 11 instead. My console outputs for the two sysouts read:

LeftSh Reads 11111111111111111010100000000000

RightSh Reads 1011

I'm learning Java on my own and feel that I missed something fundamental about either casting or bit-shifting that's causing this to happen. How do I fix this?


Solution

  • Use logical-and instead of left/right shift, to avoid issues with the fact that short is signed:

    short i = 1557;
    
    short i_masked = (short)(i & 0x001F);
    

    or, perhaps more clearly

    short i_masked = (short) (i & 0b0000000000011111);
    

    To understand what is happening in your code I suggest you print out the value after right-shifting but before applying abs().