【问题标题】:Rotating bits of any integer in CC中任何整数的旋转位
【发布时间】:2010-10-13 22:45:36
【问题描述】:

将一个整数 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;   
}

【问题讨论】:

  • 考虑>>和
  • 你的问题是?你想知道按位运算吗? en.wikipedia.org/wiki/…
  • 你真的需要学会缩进你的代码。它使您的代码更具可读性。此外,您会工作得更快,犯的错误更少。

标签: c integer rotation bit


【解决方案1】:

所以,我假设您知道什么是右移和左移。而且您知道算术移位和逻辑移位之间的区别。

C 只有算术移位。它不做逻辑移位,也不做旋转。好吧,我撒谎了,C 对无符号整数进行逻辑移位。

旋转确实如此:它与逻辑移位相同,除了当您移动超过数字的末尾时,数字“环绕”到另一侧。例如

0010 右旋为0001。如果你再次右转,你会得到1000。看,1 环绕或旋转到整数的另一侧。

左旋转类似:0100左旋转1000左旋转0001左旋转0010

请注意,旋转不会像算术右移那样保留符号位。

所以,C 只有算术移位。所以你必须手动实现“旋转”部分。所以,左转。你会想要:

  1. 捕获最左边位的值。 (是 0 还是 1?)
  2. 左移
  3. 根据我们从第 1 步捕获的内容,将最右边的位 - 我们在第 1 步中讨论过的位(需要旋转)设置为正确的值。

您应该能够找出类似的右旋方法。

祝你好运!

【讨论】:

  • 对不起,有相反的意思;有符号量的右移是算术还是逻辑取决于各个 C 编译器——ISO 标准明确地未定义它。这只是迂腐,只是坚持无符号值。
  • @poundifdef 旋转 1 很好,但是旋转 n 怎么样?
【解决方案2】:

接受的答案非常好,直截了当。

但是,我正在做一些 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 参数。

请注意,此功能偏向于可教性/易读性/简单性,而不是效率/便携性/紧凑性。

【讨论】:

  • 另外,如果你想可视化你的结果,你可以使用这个很好的函数,将单词的位组件打印到控制台:stackoverflow.com/a/1024414/269753
  • 注意,通过定义bit_width = sizeof(inputWord) * 8;,这可以变得更加通用(传入 uint64_t 等)
  • @ideasman42:谢谢,这很好。我更新了代码。
【解决方案3】:

由于没有人告诉你如何实现这一点,你可以使用内在函数,对于 Visual Studio,它们是 _rotl、_rotl64、_rotr、_rotr64。

哦,但轮换和轮班是两件不同的事情!

【讨论】:

    【解决方案4】:

    我也在读 K&R,所以这是一个非常简单的 unsigned int 旋转函数:

    unsigned int rightrot(unsigned int x, unsigned int n)
    {
      return (x >> n) | (x << (sizeof(int) * CHAR_BIT - n)); /* CHAR_BIT is defined in limits.h */
    }
    
    unsigned int leftrot(unsigned int x, unsigned int n)
    {
      return (x << n) | (x >> (sizeof(int) * CHAR_BIT - n));
    }
    

    其中n 是要旋转的位数。

    【讨论】:

      【解决方案5】:
      【解决方案6】:

      看来您向右旋转是正确的。 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 - 真正改变它

      去玩吧。它最终会起作用的!

      【讨论】:

        【解决方案7】:

        我建议使用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)));
        }
        

        【讨论】:

        • 这是移动而不是旋转。
        • @Olathe 这更好吗?可能会有优化,但我现在能想到的就这些了。
        • 抱歉这么久才回复您。是的,看起来不错,但您不需要 &amp; 掩码:移位将自动丢弃从末尾脱落的位。 return dir == DIR_RIGHT ? (in &gt;&gt; amount) | (in &lt;&lt; (8*sizeof(unsigned int) - amount)) : (in &lt;&lt; amount) | (in &gt;&gt; (8*sizeof(unsigned int) - amount));
        猜你喜欢
        • 2020-05-27
        • 1970-01-01
        • 1970-01-01
        • 2016-08-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-01-30
        相关资源
        最近更新 更多