0
votes

I understand that there are similar questions out there. But what I am curious about is why a logical left shift is the same as an arithmetic left shift.

I understand that an arithmetic and logical left shift are technically the same, as the msb (most significant bit) is not preserved in both the operations, and the msb is replaced with a 0, and all the bits are simply "shifted" left. But, why can't we preserve the msb whilst shifting the rest of the bits left for the left arithmetic shift? The arithmetic right shift preserves the msb to denote a signed bit, so why aren't we doing the same for arithmetic left shift?

For example, in Java: ">>>" is logical right shift, and ">>" is arithmetic right shift, but "<<" performs both arithmetic/logical left shift even if the signed bit is not preserved.

2
A left shift by 1 replaces the most significant bit with the previously-second-most significant bit - it replaces the least significant bit with 0. Of course, there would be nothing stopping you from defining your own operation which does a left shift preserving the least significant bit, but this isn't a useful enough operation for it to be a primitive in any popular languages.kaya3
So, if I'm understanding this correctly, in an arithmetic right shift, the most significant bit is preserved because an msb of 1 would be interpreted as a negative sign, and a 0 would be interpreted as a positive sign. If this is the case, why can't we do the same for arithmetic left shifts?Phillip La
When we perform an arithmetic left shift, wouldn't we want a negative number to remain negative too? Since a left shift is equivalent to a division by 2? If we simply shift left and in some cases, remove the most significant bit of 1 with the second most significant bit of 0, aren't we changing the sign of the number?Phillip La
If you shift left such that a negative number turns into a positive number, then you get the same result as if you would have multiplied by 2; either way, it is integer overflow and you don't get the "right" answer because the fixed width of the integer isn't enough to represent the "right" answer. If you instead preserved the sign bit, then you still don't get the "right" answer for multiplying by 2, for the same reason - you would just get a wrong negative result instead of a wrong positive result.kaya3

2 Answers

0
votes

But, why can't we preserve the msb whilst shifting the rest of the bits left for the left arithmetic shift?

We could do it, for example here is a java implementation of that idea:

int shiftLeftPreserveMSB(int x, int k) {
    return (x & Integer.MIN_VALUE) | ((x << k) & Integer.MAX_VALUE);
}

But is that actually useful? For example, it has the dubious property that whenever the result differs from x << k, neither of the results match (long)x << k. From an arithmetic perspective, that doesn't seem very useful. Maybe it is, but at the very least it's a strange operation. There may be other uses for an operation like this, such as in bithacks, though I don't know of any such use.

0
votes

Normal left and right arithmetic shifts both preserve the sign bits. So

-32 >> 1 == -16
-16 << 1 == -32

So a left arithmetic shift is, in a sense, both arithmetic and logical since both arithmetic and non-arithmetic bit manipulations can be done.

But a right logical shift needs to be handled specially to shift the sign bit and fill on the left with 0 bits.

-1 >>> 1 == 2147483647

This is essential if non-arithmetic bit manipulation is to be accomplished. But how would a left arithmetic shift be done that preserves the sign?

Consider a 4 bit register and the msb is the sign and it is preserved. Imagine the << operator worked as follows

0111 == 7
0111 << 1 == 0110 == 6
0110 << 1 == 0100 == 4
0100 << 1 == 0000 == 0

Imo, that would not be of much use.