Вращающиеся биты любого целого числа в C - PullRequest
0 голосов
/ 14 октября 2010

Передайте целое число 2 этой функции, а затем верните целое число, равное 4

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

(сдвиг влево битов на 1)

Пример: 00000010 -> повернуть влево на 1-> 00000100

но если я передам это:

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

, то вернется 64, 01000000

Вот код, может кто-то исправить ошибку ... спасибо

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 ]

4 голосов
/ 14 октября 2010

Итак, я предполагаю, что вы знаете, что такое сдвиги вправо и влево.И что вы знаете разницу между арифметическими и логическими сдвигами.

C имеет только арифметические сдвиги.Он не делает логических сдвигов и не вращается.ладно, я солгал, C делает логические сдвиги в неподписанных целых числах.

Поворот делает, ну, в точности то же самое: это то же самое, что и логический сдвиг, за исключением случаев, когда вы сдвигаетесь после конца числа, перенос цифр "вокруг "на другую сторону.Например,

0010 с правым поворотом - 0001.Если вы снова поверните вправо, вы получите 1000.См. 1, обернутый или повернутый к другой стороне целого числа.

Поворот влево аналогичен: 0100 Поворот влево 1000 Поворот влево 0001 Поворот влево 0010и т. д.

Обратите внимание, что при вращении не сохраняется знаковый бит, как при арифметическом сдвиге вправо.

Таким образом, C имеет только арифметические сдвиги.Таким образом, вы должны реализовать «вращать» часть вручную.Итак, поверните налево.Вы хотели бы:

  1. Захватить значение самого левого бита.(это 0 или 1?)
  2. Сделать сдвиг влево
  3. Установить самый правый бит - это тот бит, о котором мы говорили в шаге 1 (который нужно вращать вокруг) к правильному значению, основанному на том, что мы зафиксировали на шаге 1.

Вы должны быть в состоянии найти аналогичный метод для правого поворота.

удачи!

3 голосов
/ 17 февраля 2013

Принятый ответ очень приятный и прямой.

Однако я выполнял некоторые упражнения K & R для обновления своего C и хотел поделиться этой функцией поворота вправо, которая может пригодиться людям, пытающимся изучать побитовые операции.

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;
}

Для левого вращения просто передайте значения от -1 до -31 аргументу bitAmount.

Обратите внимание, что эта функция способствует обучаемости / удобочитаемости / простоте, а не эффективности / портативности / компактности.

0 голосов
/ 14 октября 2010

Поскольку никто не говорил вам, как реализовать это, вы можете использовать встроенные функции, для visual studio это _rotl, _rotl64, _rotr, _rotr64.

Да, но вращение и сдвиг - это две разные вещи!

0 голосов
/ 14 октября 2010

Я рекомендую использовать 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)));
}
0 голосов
/ 14 октября 2010

Кажется, что ваш поворот направо - ВПРАВО.1 упал на бок и вернулся обратно слева?

В любом случае, вот ваши ингредиенты:

http://tigcc.ticalc.org/doc/keywords.html#if - для определения, является ли это 'L' или 'R'

http://tigcc.ticalc.org/doc/keywords.html#for - для подсчета количества сдвигов

и

http://msdn.microsoft.com/en-us/library/f96c63ed(VS.80).aspx - для фактического сдвига

Иди, играй с этим.Это будет работать в конце концов!

0 голосов
/ 14 октября 2010

Посмотрите на операторы побитового сдвига:

http://en.wikipedia.org/wiki/Bitwise_operators#Shifts_in_C.2C_C.2B.2B_and_Java

...