左旋转 BigInteger?
Left rotate BigInteger?
有没有办法正确地向左旋转(而不仅仅是移位)固定大小的 BigIntegers?
我尝试编写一种类似于用于旋转整数的经典旋转方法的方法,但它不适用于 BigIntegers。它只是将位向左移动 r 个位置,最后填充零。
public static BigInteger rotate(BigInteger n, int r){
return n.shiftLeft(r).or(n.shiftRight(128-r));
}
编辑:不使用 BigIntegers 而使用 long 或整数数组看起来像是另一种选择,但我不确定您如何将它们组合起来(使用 BigIntegers 除外)来执行旋转。
其实并不那么容易。旋转点在哪里?这对于 32 位或 64 位整数等固定大小的数字很容易,但对于 BigIntegers 则不然。
但是...理论上,BigIntegers 的大小和二进制补码是无限的(或者至少,它们的行为就像它们一样,实际上它们通常是符号大小)。所以正数(实际上)前面有无限数量的 0 位和负数前面有无限数量的 1 位。
所以向左旋转1实际上就是向左移动1,如果数字was/is为负数,则最低位设置为1。
更新
如果BigInteger只是用来表示一个固定大小整数(BigIntegers本身没有固定大小),你将不得不把高位移到低位。然后你可以这样做:
public static BigInteger rotateLeft(BigInteger value, int shift, int bitSize)
{
// Note: shift must be positive, if necessary add checks.
BigInteger topBits = value.shiftRight(bitSize - shift);
BigInteger mask = BigInteger.ONE.shiftLeft(bitSize).subtract(BigInteger.ONE);
return value.shiftLeft(shift).or(topBits).and(mask);
}
你这样称呼它:
public static void main(String[] args)
{
BigInteger rotated = rotateLeft(new
BigInteger("1110000100100011010001010110011110001001101010111100110111101111" +
"1111111011011100101110101001100001110110010101000011001000010010",
2), 7, 128);
System.out.println(rotated.toString(2));
}
注意:我确实对此进行了测试,它似乎产生了预期的结果:
10010001101000101011001111000100110101011110011011110111111111110110111001011101010011000011101100101010000110010000100101110000
如果 bitSize 是固定的(例如始终为 128),您可以预先计算掩码,当然不必将 bitSize 传递给函数。
编辑:
要获得掩码,而不是向左移动BigInteger.ONE
,你也可以这样做:
BigInteger.ZERO.setBit(bitSize).subtract(BigInteger.ONE);
这可能会快一点。
有没有办法正确地向左旋转(而不仅仅是移位)固定大小的 BigIntegers?
我尝试编写一种类似于用于旋转整数的经典旋转方法的方法,但它不适用于 BigIntegers。它只是将位向左移动 r 个位置,最后填充零。
public static BigInteger rotate(BigInteger n, int r){
return n.shiftLeft(r).or(n.shiftRight(128-r));
}
编辑:不使用 BigIntegers 而使用 long 或整数数组看起来像是另一种选择,但我不确定您如何将它们组合起来(使用 BigIntegers 除外)来执行旋转。
其实并不那么容易。旋转点在哪里?这对于 32 位或 64 位整数等固定大小的数字很容易,但对于 BigIntegers 则不然。
但是...理论上,BigIntegers 的大小和二进制补码是无限的(或者至少,它们的行为就像它们一样,实际上它们通常是符号大小)。所以正数(实际上)前面有无限数量的 0 位和负数前面有无限数量的 1 位。
所以向左旋转1实际上就是向左移动1,如果数字was/is为负数,则最低位设置为1。
更新
如果BigInteger只是用来表示一个固定大小整数(BigIntegers本身没有固定大小),你将不得不把高位移到低位。然后你可以这样做:
public static BigInteger rotateLeft(BigInteger value, int shift, int bitSize)
{
// Note: shift must be positive, if necessary add checks.
BigInteger topBits = value.shiftRight(bitSize - shift);
BigInteger mask = BigInteger.ONE.shiftLeft(bitSize).subtract(BigInteger.ONE);
return value.shiftLeft(shift).or(topBits).and(mask);
}
你这样称呼它:
public static void main(String[] args)
{
BigInteger rotated = rotateLeft(new
BigInteger("1110000100100011010001010110011110001001101010111100110111101111" +
"1111111011011100101110101001100001110110010101000011001000010010",
2), 7, 128);
System.out.println(rotated.toString(2));
}
注意:我确实对此进行了测试,它似乎产生了预期的结果:
10010001101000101011001111000100110101011110011011110111111111110110111001011101010011000011101100101010000110010000100101110000
如果 bitSize 是固定的(例如始终为 128),您可以预先计算掩码,当然不必将 bitSize 传递给函数。
编辑:
要获得掩码,而不是向左移动BigInteger.ONE
,你也可以这样做:
BigInteger.ZERO.setBit(bitSize).subtract(BigInteger.ONE);
这可能会快一点。