我正在努力想出一个函数int rotateRight (int x, int n)
,x
向右移动n
rotateRight(0x87654321,4) = 0x76543218
。例如,
int rotateRight(int x, int n) {
int mask = (((1 << n)-1)<<(32-n));
int reserve = (int)((unsigned) (x&mask) >>(32-n));
return (x << n) | reserve;
}
这是我到目前为止所做的:
~
但是,我禁止使用任何广告投放,允许的操作是&
^
|
+
<<
>>
和{ {1}}。任何人都可以帮我解决这个问题吗?
答案 0 :(得分:3)
基本上你所要做的就是:
使用右移将所有内容右移n位:>>
将您要旋转的位一直向左移动:<<
将移位的右移位和左移位与or
合并:|
使用您需要的函数签名查看此代码以获取示例实现:
int rotateRight(int x, int n) {
//if n=4, x=0x12345678:
//shifted = 0x12345678 >> 4 = 0x01234567
int shifted = x >> n;
//rot_bits = (0x12345678 << 28) = 0x80000000
int rot_bits = x << (32-n);
//combined = 0x80000000 | 0x01234567 = 0x81234567
int combined = shifted | rot_bits;
return combined;
}
这种实施方式并不安全,至少在没有一些保证的情况下 - 即x
始终为正,n
为正,始终为<= 32
。
如果传入一个负整数进行移位,它将无法正常工作,因为它会对最左边的位进行符号扩展。如果您希望此函数适用于所有整数,则应将所有类型从int
更改为unsigned int
(这样就不会发生符号扩展或负向左移),然后以模{{{ 1}} by 32(n
)。这是函数的安全版本:
% 32
为你的极简主义者打高尔夫球:
unsigned int rotateRight(unsigned int x, unsigned int n) {
//needed so you don't right shift more than int width
n %= 32;
//needed so you don't left shift more than int width
unsigned int leftshift_val = (32-n) % 32
unsigned int shifted = x >> n;
unsigned int rot_bits = x << leftshift_val;
unsigned int combined = shifted | rot_bits;
return combined;
}
答案 1 :(得分:1)
通过左右移位的组合完成旋转。
移位有符号整数的符号位是个问题。建议转换为unsigned
以执行转换。 @The Paramagnetic Croissant
实现定义行为的一个示例是当有符号整数向右移位时传输高阶位。
移位位宽或更大是一个问题。将实际转移限制为n modulo Bit_width
。 (...<<(32-n));
时,OP n == 0
代码存在问题。
OP的例子看起来更像是左旋转。将假设该功能应该向右旋转。 (0x87654321,4)
- &gt; 0x18765432
。 @Mark Shevchenko
int
的宽度不得超过32。
#include <limits.h>
#define INT_BIT_WIDTH (sizeof (int) * CHAR_BIT)
int rotateRight(int x, int n) {
unsigned xu = x;
unsigned nu = n;
nu %= INT_BIT_WIDTH;
unsigned y = xu >> nu;
if (nu > 0) {
y |= xu << (INT_BIT_WIDTH - nu);
}
return y;
}
[编辑]由于OP仅限于~ & ^ | + << >>
,请使用以下替代代码
注意:在极少数情况下,int
的宽度不是2的幂,这是一个问题。
// nu %= INT_BIT_WIDTH;
nu &= INT_BIT_WIDTH - 1;
[编辑2]以为我会形成一个unsigned
简约解决方案,受到@RPGillespie的启发,因为OP无法使用%
。
#include <limits.h>
#define UNS_WIDTH (sizeof (unsigned) * CHAR_BIT)
#define UNS_WIDTH_M1 (UNS_WIDTH - 1)
unsigned unsigned_rotate_right(unsigned x, unsigned n) {
return (x >> (n & UNS_WIDTH_M1)) | (x << ((UNS_WIDTH - n) & UNS_WIDTH_M1));
}
答案 2 :(得分:0)
根据this explanation,可以通过以下实现完成轮换。
#include<stdio.h>
#define INT_BITS 32
/*Function to left rotate n by d bits*/
int leftRotate(int n, unsigned int d)
{
/* In n<<d, last d bits are 0. To put first 3 bits of n at
last, do bitwise or of n<<d with n >>(INT_BITS - d) */
return (n << d)|(n >> (INT_BITS - d));
}