简体   繁体   English

在C ++中有效地右移二进制字符串

[英]Right shift a binary string efficiently in C++

If I have a string that represents an integer in binary form such as 如果我有一个以二进制形式表示整数的字符串,例如

1101101

and I want to circularly right shift it to obtain 我想循环右移以获得

1110110

One way I could think of would be converting the string into an int and use (taken from wikipedia ) 我想到的一种方法是将字符串转换为int并使用(摘自Wikipedia

// https://stackoverflow.com/a/776550/3770260
template <typename INT>
#if __cplusplus > 201100L // Apply constexpr to C++ 11 to ease optimization
constexpr
#endif // See also https://stackoverflow.com/a/7269693/3770260
INT rol(INT val, size_t len) {
#if __cplusplus > 201100L && _wp_force_unsigned_rotate // Apply unsigned check C++ 11 to make sense
    static_assert(std::is_unsigned<INT>::value,
                  "Rotate Left only makes sense for unsigned types");
#endif
    return (val << len) | ((unsigned) val >> (-len & (sizeof(INT) * CHAR_BIT - 1)));
}

However, if the string consists of, say, 10^6 char then this does not work as the integer representation exceeds even the range of __int64 . 但是,如果字符串由10 ^ 6 char组成,则此操作不起作用,因为整数表示甚至超过了__int64的范围。

In that case I could think of a solution by looping over the string 在那种情况下,我可以通过遍历字符串来考虑解决方案

//let str be a char string of length n
char temp = str[n - 1];
for(int i = n - 1; i > 0; i--)
{
    str[i] = str[i - 1];
}
str[0] = temp;

This solution runs in O(n) due the loop over the length of the string, n. 由于在字符串n的长度上存在循环,因此该解决方案在O(n)运行。 My question is, is there much more efficient way to implement circular shifting for large binary strings? 我的问题是,对于大型二进制字符串,有没有更有效的方法来实现循环移位?

EDIT 编辑

Both input and output are std::string s 输入和输出都是std::string s

You have to move memory one way or another, so your proposed solution is as fast as it gets. 您必须以一种或另一种方式移动内存,因此您提出的解决方案要尽可能快。

You might also use standard std::string functions: 您可能还使用标准的std::string函数:

str.insert(str.begin(), str[n - 1]);
str.erase(str.end() - 1);

or memmove , or memcpy (I don't actually recommend this, it's for an argument) memmovememcpy (我实际上不建议这样做,这是为了争论)

char temp = str[n - 1];
memmove(str.data() + 1, str.data(), n - 1);
str[0] = temp;

Note that memmove may look faster, but it's essentially the same thing as your loop. 请注意, memmove外观可能更快,但这与循环本质上是一样的。 It is moving bytes one by one, it's just encapsulated in a different function. 它正在逐字节移动字节,只是封装在其他函数中。 This method might be faster for much larger data blocks, of size 1000 bytes or more, since the CPU is optimized to move large chunks of memory. 这种方法对于更大的数据块(大小为1000字节或更大)可能更快,因为CPU已优化为移动大块内存。 But you won't be able to measure any difference for 10 or 20 bytes. 但是您将无法测量10或20个字节的差异。

Moreover, the compiler will most likely run additional optimizations when it sees your for loop, it realizes that you are moving memory and chooses the best option. 此外,当编译器看到您的for循环时,很可能会运行其他优化,它意识到您正在移动内存并选择最佳选项。

The compiler is also good at dealing with std::string methods. 编译器还擅长处理std::string方法。 These are common operations and the compiler knows the best way to handle it. 这些是常见的操作,编译器知道处理它的最佳方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM