I\'m working on making a logical right shift function in C using only bitwise operators. Here\'s what I have:
int logical_right_shift(int x, int n)
{
int
This is what you need:
int logical_right_shift(int x, int n)
{
int size = sizeof(int) * 8; // usually sizeof(int) is 4 bytes (32 bits)
return (x >> n) & ~(((0x1 << size) >> n) << 1);
}
Explain
x >> n
shifts n bits
right. However, if x
is negative, the sign bit (left-most bit) will be copied to its right, for example:
Assume every int is 32 bits here, let
x = -2147483648 (10000000 00000000 00000000 00000000)
, then
x >> 1 = -1073741824 (11000000 00000000 00000000 00000000)
x >> 2 = -536870912 (11100000 00000000 00000000 00000000)
and so on.
So we need to erase out those sign extra sign bits when n is negative.
Assume n = 5
here:
0x1 << size
moves 1
to the left-most position:
(10000000 00000000 00000000 00000000)
((0x1 << size) >> n) << 1
copies 1 to its n-1
neighbors:
(11111000 00000000 00000000 00000000)
~((0x1 << size) >> n) << 1!
reverses all bits:
(00000111 11111111 11111111 11111111)
so we finally obtain a mask to extract what really need from x >> n
:
(x >> n) & ~(((0x1 << size) >> n) << 1)
the &
operation does the trick.
And the total cost of this function is 6
operations.
I think problem is in your ">> (n-1)" part. If n is 0 then left part will be shift by -1. So,here is my solution
int logical_right_shift(int x, int n)
{
int mask = ~(-1 << n) << (32 - n);
return ~mask & ( (x >> n) | mask);
}
As with @Ignacio's comment, I don't know why you would want to do this (without just doing a cast to unsigned
like in the other answers), but what about (assuming two's complement and binary, and that signed shifts are arithmetic):
(x >> n) + ((1 << (sizeof(int) * CHAR_BIT - n - 1)) << 1)
or:
(x >> n) ^ ((INT_MIN >> n) << 1)
Just store your int
in an unsigned int
, and perform >>
upon it.
(The sign is not extended or preserved if you use unsigned int)
http://en.wikipedia.org/wiki/Logical_shift
int lsr(int x, int n)
{
return (int)((unsigned int)x >> n);
}
Milnex's answer is great and has an awesome explanation, but the implementation unfortunately fails due to the shift by total size. Here is a working version:
int logicalShift(int x, int n) {
int totalBitsMinusOne = (sizeof(int) * 8) - 1; // usually sizeof(int) is 4 bytes (32 bits)
return (x >> n) & ~(((0x1 << totalBitsMinusOne) >> n) << 1);
}
To have 1 as the most significant bit, and all zeroes elsewhere, we need to shift 0x1
by number of bits - 1
. I am submitting my own answer because my edit to the accepted answer was somehow rejected.