我想在我的整数类中实现无符号左旋转。但是,因为它是一个模板类,它可以是从 128 位开始的任何大小,并继续下去;所以我不能使用需要相同大小的临时的算法,因为如果类型变大,就会发生堆栈溢出(特别是如果这样的函数在调用链中)。
因此,为了解决这样的问题,我将其最小化为一个问题:我必须执行哪些步骤才能仅使用 4 位来旋转 32 位数字。好吧,如果您考虑一下,它是一个 32 位数字,包含 8 组,每组 4 位,因此如果要旋转的位数是 4,那么组之间会发生交换0 and 4
,1 and 5
, 2 and 6
, 3 and 7
, 之后旋转完成。
如果要旋转的位小于 4 且大于 0,那么很简单,只需保留最后一位N
并开始移位或循环,例如,假设我们有将0x9CE2
其左旋转 3 位的数字,我们将执行以下操作:
little endian 二进制中的数字是1001 1100 1110 0010
,每个半字节从右到左从 0 到 3 索引,我们将这个数字N
和一组中的位数称为B
[1] x <- N[3] >> 3
x <- 1001 >> 3
x <- 0100
y <- N[0] >> (B - 3)
y <- N[0] >> (4 - 3)
y <- 0010 >> 1
y <- 0001
N[0] <- (N[0] << 3) | x
N[0] <- (0010 << 3) | 0100
N[0] <- 0000 | 0100
N[0] <- 0100
[2] x <- y
x <- 0001
y <- N[1] >> (B - 3)
y <- N[1] >> (4 - 3)
y <- 1110 >> 1
y <- 0111
N[1] <- (N[1] << 3) | x
N[1] <- (1110 << 3) | 0001
N[1] <- 0000 | 0001
N[1] <- 0001
[3] x <- y
x <- 0111
y <- N[2] >> (B - 3)
y <- N[2] >> (4 - 3)
y <- 1100 >> 1
y <- 0110
N[2] <- (N[2] << 3) | x
N[2] <- (1100 << 3) | 0111
N[2] <- 0000 | 0111
N[2] <- 0111
[4] x <- y
x <- 0110
y <- N[3] >> (B - 3)
y <- N[3] >> (4 - 3)
y <- 1001 >> 1
y <- 0100
N[3] <- (N[3] << 3) | x
N[3] <- (1001 << 3) | 0110
N[3] <- 1000 | 0110
N[3] <- 1110
结果是1110 0111 0001 0100
,0xE714
以十六进制表示,这是正确的答案;并且,如果您尝试以任何精度将其应用于任何数字,您所需要的只是一个变量,该变量的类型是形成该 bignum 类型的数组的任何元素的类型。
现在真正的问题是当要旋转的位数大于一组或大于类型的一半时(即在此示例中大于 4 位或 8 位)。
通常,我们将位从最后一个元素移到第一个元素,依此类推;但是现在,在将最后一个元素移动到第一个元素之后,结果必须重新定位到新的位置,因为要旋转的位数大于元素上的位数(即> 4 bits
)。移位开始的起始索引是最后一个索引(本例中为 3),对于目标索引,我们使用dest_index = int(bits_count/half_bits) + 1
等式:第一次移位的结果必须重新定位到目标索引 2——这是我的问题,因为我想不出一种方法来为这种情况编写算法。half_bits
half_bits = 8
bits_count = 7
dest_index = int(7/8) + 1 = 1 + 1 = 2
谢谢。