Rotating bits of any integer in C

2019-02-21 05:01发布

Pass a integer 2 to this function and then return a integer which is 4

x = 2;
x = rotateInt('L', x, 1); 

(left shift the bits by 1)

Example: 00000010 -> rotate left by 1 -> 00000100

but if I pass this:

x = rotateInt('R', x, 3); 

it will return 64, 01000000

Here is the code, can someone correct the error... thanks

int rotateInt(char direction, unsigned int x, int y)
{
    unsigned int mask = 0;
    int num = 0, result = 0;
    int i;

    for (i = 0; i < y; i++)
    {     
        if (direction == 'R')
        {
            if ((x & 1) == 1)     
                x = (x ^ 129);
            else    
                x = x >> 1;
        }
        else if (direction == 'L')
        {
            if ((x & 128) == 1)  
                x = (x ^ 129);   
            else
                x = x << 1;
        }
    }
result = (result ^ x);
return result;   
}

6条回答
做自己的国王
2楼-- · 2019-02-21 05:21

So, I'll assume you know what right and left shifts are. And that you know the difference between arithmetic and logical shifts.

C only has arithmetic shifts. It doesn't do logical shifts, nor does it do rotates. okay I lied, C does logical shifts on unsigned ints.

A rotate does, well, exactly that: it's the same as a logical shift, except when you shift past the end of the number, the digits "wrap around" to the other side. For example

0010 right-rotated is 0001. If you right-rotate again, you get 1000. See, the 1 wrapped around, or rotated, to the other side of the integer.

The left rotate is similar: 0100 left rotate 1000 left rotate 0001 left rotate 0010 etc.

Note that rotates don't keep the sign bit as an arithmetic right-shift would.

So, C only has arithmetic shifts. So you have to implement the "rotate" part manually. So, take a left-rotate. You would want to:

  1. Capture the value of the left-most bit. (is it a 0 or 1?)
  2. Do a left-shift
  3. Set the right-most bit - which is the bit we talked about in step 1 (which needs to be rotated around) to the correct value, based on what we captured from step 1.

You should be able to figure out a similar method for right rotates.

good luck!

查看更多
叛逆
3楼-- · 2019-02-21 05:29

It seems like your rotate to the right is RIGHT. 1 fell of the side and returned back again from the left?

Anyway, here are your ingredients:

http://tigcc.ticalc.org/doc/keywords.html#if - for determining if it is 'L' or 'R'

http://tigcc.ticalc.org/doc/keywords.html#for - for counting number of times to shift

and

http://msdn.microsoft.com/en-us/library/f96c63ed(VS.80).aspx - to actually shift it

Go, play with it. It WILL work eventually!

查看更多
聊天终结者
4楼-- · 2019-02-21 05:36

Since no one told you how to implement this, you can use intrinsics, for visual studio they are _rotl, _rotl64, _rotr, _rotr64.

Oh, but rotation and shifts are 2 different things!

查看更多
神经病院院长
5楼-- · 2019-02-21 05:36

I recommend using an unsigned int.

#define DIR_LEFT 0
#define DIR_RIGHT 1

unsigned int rotateInt(unsigned int in, int amount, byte dir)
{
    return(dir == DIR_RIGHT ? (in >> amount) | ((in & ((0x01 << amount) - 1)) << (sizeof(unsigned int)*8 - amount)) : (in << amount)  | ((in & ~((sizeof(unsigned int)*8*8 - 1) >> amount)));
}
查看更多
趁早两清
6楼-- · 2019-02-21 05:40
\"骚年 ilove
7楼-- · 2019-02-21 05:42

The accepted answer is very nice and straight-forward.

However, I was doing some K&R exercises to refresh my C, and wanted to share this rotate-to-the-right function which may come in handy for people trying to learn bit-wise operations.

unsigned int rightRotateBits(unsigned int inputWord, int numberOfBitsToRotate) {
    int bitWidth = sizeof(inputWord) * 8;
    // Rotating 32 bits on a 32-bit integer is the same as rotating 0 bits;
    //   33 bits -> 1 bit; etc.
    numberOfBitsToRotate = numberOfBitsToRotate % bitWidth;

    unsigned int tempWord = inputWord;

    // Rotate input to the right
    inputWord = inputWord >> numberOfBitsToRotate;

    // Build mask for carried over bits
    tempWord = tempWord << (bitWidth - numberOfBitsToRotate);

    return inputWord | tempWord;
}

For left-rotations just pass values between -1 and -31 to the bitAmount argument.

Do note that this function favors teachability/legibility/simplicity over efficiency/portability/compactness.

查看更多
登录 后发表回答