【C程序设计语言第二版】练习2-8:将x循环右移n位

解题思路

我们可以用一个变量rbit来记录x最右边的位移到最左端的位置(len(x) - 1),然后我们把x右移一位,再对右移后的x与rbit进行或操作,这就完成了一次对x的循环右移操作,我们操作n次即可完成。

//计算出运行程序的计算机所使用的字长
int wordlength()
{
    int i;
    unsigned v = (unsigned) ~0;
    for(int i = 1; (v = v >> 1) > 0; ++i);
    return i;
}

unsigned rightrot(unsigned x, int n)
{
    int len = wordlength();
    int rbit;
    while(n-- > 0) {
        rbit = (x & 1) << (len - 1);
        x = x >> 1;
        x = x | bit;
    }
    return x;
}

优化解法

如果对x进行循环右移的总位数n与一个无符号整数的二进制位数(即这台计算机的字长)相等,完成这些次循环右移后的结果将于x完全一样,因此我们就不必对x进行循环右移了。如果n小于这台计算机的字长,那我们就必须把x循环右移n位,如果n大于这台计算机的字长,那么我们只需利用取模运算求出n对这台计算机字长的余数,再把x循环右移这个余数所代表的次数。基于上述分析,我们得出了一个无需使用循环语句的解决方案。
~0 << n:把一个全1的屏蔽码左移n为,在它最右端制造n位0。
~(~0 << n) : 把这个屏蔽码最右端的n位设置为1,其余位设置为0。

当我们用这个屏蔽码和x进行与运算是,x的最右端n位将被赋值给变量rbits,然后将rbits中的1左移到它的最左端,把x右移n位,再对右移后的x和rbits进行或运算就完成了。

unsigned rightrot(unsigned x, int n)
{
    int len = wordlength();
    unsigned rbits;
    if((n == n % len) > 0) {
        rbits = ~(~0 << n) & x;
        rbits = rbits << (len - n);
        x = x >> n;
        x = x | rbits;
    }
    return x;
}
发布了128 篇原创文章 · 获赞 20 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/u011544909/article/details/95801480