Stacking_Flow
Stacking_Flow

Reputation: 125

Why is Logical Shift Left the Same as Arithmetic Shift Left?

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.

Upvotes: 1

Views: 3069

Answers (2)

WJS
WJS

Reputation: 40057

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.

Upvotes: 0

user555045
user555045

Reputation: 64913

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.

Upvotes: 0

Related Questions