按位旋转(循环移位) 我试图在C++中编写一些关于“按位旋转”的代码,我想用左边的SHIF来做。我不知道如何编写代码,但我在“维基百科”中找到了这样一个小代码 unsigned int rotl(unsigned int value, int shift) { return (value << shift) | (value >> (sizeof(value) * CHAR_BIT - shift)); } unsigned int rotl(unsigned int value,int shift){ 返回(值>(sizeof(值)*字符位移位)); }

按位旋转(循环移位) 我试图在C++中编写一些关于“按位旋转”的代码,我想用左边的SHIF来做。我不知道如何编写代码,但我在“维基百科”中找到了这样一个小代码 unsigned int rotl(unsigned int value, int shift) { return (value << shift) | (value >> (sizeof(value) * CHAR_BIT - shift)); } unsigned int rotl(unsigned int value,int shift){ 返回(值>(sizeof(值)*字符位移位)); },c++,bit-manipulation,C++,Bit Manipulation,然后我试着让它工作,但这段代码没有给出我期望的输出。例如,我有一个数字无符号整数12,二进制1100,当我想用上面的代码按左移位进行位旋转时,输出是和无符号整数24,(11000),它必须给出输出无符号整数9,因为如果我进行位旋转(左移位),第一个MSB位现在必须是第一位,所有其他位必须向左移动一位 你能帮我弄明白这是什么问题吗?或者我做错了什么 谢谢。这是因为您使用的是32位的int,所以它按照预期工作,将最重要的位包装到前面。使用较小的数据结构,如无符号字符,使其更易于管理。整数中有4位以上

然后我试着让它工作,但这段代码没有给出我期望的输出。例如,我有一个数字
无符号整数12
,二进制1100,当我想用上面的代码按左移位进行位旋转时,输出是和
无符号整数24
,(11000),它必须给出输出
无符号整数9
,因为如果我进行位旋转(左移位),第一个MSB位现在必须是第一位,所有其他位必须向左移动一位

你能帮我弄明白这是什么问题吗?或者我做错了什么


谢谢。

这是因为您使用的是32位的
int
,所以它按照预期工作,将最重要的位包装到前面。使用较小的数据结构,如
无符号字符
,使其更易于管理。

整数中有4位以上,很可能是32位,但理论上可能是64位或16位。因此,值12的位是0000000000000000000000 1100。按1进行左旋转自然会得到值00000000000000000000011000(=24)。

如果希望在任意位数上进行按位旋转(例如4),只需向函数中添加一个参数:

unsigned int rotl(unsigned int value, int shift, unsigned int width) {
    return ((value << shift) & (UINT_MAX >> (sizeof(int) * CHAR_BIT - width))) | (value >> (width - shift));
}
unsigned int rotl(unsigned int value、int shift、unsigned int width){
返回((值>(sizeof(int)*CHAR_BIT-width)))|(值>>(width-shift));
}

以下代码非常有效

#include <cstdint>

std::uint32_t rotl(std::uint32_t v, std::int32_t shift) {
    std::int32_t s =  shift>=0? shift%32 : -((-shift)%32);
    return (v<<s) | (v>>(32-s));
}

std::uint32_t rotr(std::uint32_t v, std::int32_t shift) {
    std::int32_t s =  shift>=0? shift%32 : -((-shift)%32);
    return (v>>s) | (v<<(32-s));
}
#包括
std::uint32_t旋转(std::uint32_t v,std::int32_t移位){
std::int32\u t s=shift>=0?移位%32:-(-shift)%32);
返回(v(32-s));
}
std::uint32\U t rotr(std::uint32\U t v,std::int32\U t shift){
std::int32\u t s=shift>=0?移位%32:-(-shift)%32);

return(v>>s)|(vC++20在
标题中提供
std::rotl
std::rotr
。示例如下:

#包括
#包括
#包括
#包括
int main()
{
标准:uint8_t i=0b00011101;

std::cout如果不使用C++20,可能需要两个助手函数,如:

template< std::size_t N >
[[ nodiscard ]] std::bitset< N > rotl( std::bitset< N > b, std::size_t const n ) noexcept
{
    return b << n | b >> ( N - n );
}

template< std::size_t N >
[[ nodiscard ]] std::bitset< N > rotr( std::bitset< N > b, std::size_t const n ) noexcept
{
    return b >> n | b << ( N - n );
}
模板
[[nodiscard]]std::bitsetrotl(std::bitsetb,std::size\u t const N)无例外
{
返回b>(N-N);
}
模板
[[nodiscard]]std::bitsetrotr(std::bitsetb,std::size\u t const N)无例外
{

返回b>>n | b,那么您的值是4位宽?您显示的代码适用于类型为
无符号int
的值,该值远远大于4位。您的函数是正确的。整数有32位,而不是4位。@GregHewgill您说的是“经典旋转移位”,但OP要求的是另一件事。这可能是误解了什么“循环移位”的意思是,你对字符的定义是什么 用8测试它,它输出24。函数看起来正常,并实现循环移位(通常理解)。也就是说,如果你将一个数字移位1,则位
31
将转到位置
0
,而不管它的值如何。你在示例中所期望的和说明的是完全不同的。你还需要将答案隐藏到正确的位数。我认为你的公式也有点不正确。
*字符位
在这里是错误的,假设
width
是位,而不是字节。你的意思是:
返回((1U(width-shift));
if
测试应该是
if(width>sizeof(value)*CHAR u位)
,但这似乎是隐含的。不需要在那里添加分支,这会使测试比需要的慢得多。忘记了“#include”并且必须删除通用版本代码中的“sizeof(v)”(使用CHAR_位)。任何编辑器都可以获得自由点数。如果不使用汇编指令,我很难找到更快的版本
#include <cstdint>

template< class T>
inline T rotl( T v, std::int32_t shift){
    std::size_t m = sizeof(v)*std::numeric_limits<T>::digits;
    T s = shift>=0? shift%m: -((-shift)%m)
    return (v<<s) | (v>>(m-s));
}

template< class T>
inline T rotr( T v, std::int32_t shift){
    std::size_t m = sizeof(v)*std::numeric_limits<T>::digits;
    T s = shift>=0? shift%m: -((-shift)%m)
    return (v>>s) | (v<<(m-s));
}
template< std::size_t N >
[[ nodiscard ]] std::bitset< N > rotl( std::bitset< N > b, std::size_t const n ) noexcept
{
    return b << n | b >> ( N - n );
}

template< std::size_t N >
[[ nodiscard ]] std::bitset< N > rotr( std::bitset< N > b, std::size_t const n ) noexcept
{
    return b >> n | b << ( N - n );
}