如果之前有人问过/回答过这个问题,我深表歉意,但说实话,我什至不确定如何正确地表达这个问题。我有以下位模式:
0110110110110110110110110110110110110110110110110110110110110110
我正在尝试进行一次转变,以保留我的基本模式;我的第一直觉是使用右旋转 ((x >> count) | (x << (-count & 63)))
但我的位模式的不对称导致:
0011011011011011011011011011011011011011011011011011011011011011
<---错误
问题是最高有效位(最左边)最终是 0,而不是所需的 1:
1011011011011011011011011011011011011011011011011011011011011011
<---右
我正在寻找的这个函数有一个通俗的名称吗?如果没有,我该如何实现这个想法?
其他信息:
- 虽然这个问题与语言无关,但我目前正在尝试使用 C# 来解决这个问题。
- 我使用的位模式是完全可预测的,并且始终具有相同的结构;该模式以一个零开头,后跟
n - 1
个(其中n
是奇数),然后无限重复。 - 我想在没有条件操作的情况下完成此任务,因为它们首先就违背了使用按位操作的目的,但也许我别无选择......
最佳答案
您的数字结构如下:
B16 B15 B14 B13 B12 B11 B10 B09 B08 B07 B06 B05 B04 B03 B02 B01 B00
? 0 1 1 0 1 1 0 1 1 0 1 1 0 1 1 0
?
需要在移位后出现在 MSB(B15 或 B63 或其他)中。它从何而来?好吧,找到了最接近的副本 n
右边的地方:
B13 0 1 1 0 1 1 0 1 1 0 1 1 0 1 1 0
^--------------/
如果你的单词有宽度 w
,这是1 << (w-n)
*
所以你可以这样做:
var selector = 1 << (w-n);
var rotated = (val >> 1) | ((val & selector) << (n-1));
但您可能需要多类制。然后我们需要构建一个更宽的掩模:
? 0 1 1 0 1 1 0 1 1 0 1 1 0 1 1 0
* * * * *
在这里我选择假装n = 6
,它只需要是基本 n
的倍数即可,并且大于shift
。现在:
var selector = ((1UL << shift) - 1) << (w - n);
var rotated = (val >> shift) | ((val & selector) << (n - shift));
使用您的模式进行工作演示:http://rextester.com/UWYSW47054
很容易看出输出的周期为 3,符合要求:
1:B6DB6DB6DB6DB6DB 2:DB6DB6DB6DB6DB6D 3:6DB6DB6DB6DB6DB6 4:B6DB6DB6DB6DB6DB 5:DB6DB6DB6DB6DB6D 6:6DB6DB6DB6DB6DB6 7:B6DB6DB6DB6DB6DB 8:DB6DB6DB6DB6DB6D 9:6DB6DB6DB6DB6DB6 10:B6DB6DB6DB6DB6DB 11:DB6DB6DB6DB6DB6D
关于c# - 移位同时保留模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45599188/