左旋BigInteger?

时间:2017-04-22 15:29:14

标签: bit-manipulation bitwise-operators biginteger bit-shift

有没有办法正确地左旋(不仅仅是移位)固定大小的BigIntegers?

我尝试编写一种方法,类似于用于旋转整数的经典旋转方法,但它不适用于BigIntegers。它只是将位向左移位r位置,最后填充零。

public static BigInteger rotate(BigInteger n, int r){
        return n.shiftLeft(r).or(n.shiftRight(128-r));
    }

编辑:不使用BigIntegers并使用long或整数数组看起来像另一个选项,但我不确定你是如何组合它们(除了使用BigIntegers)来执行旋转。

1 个答案:

答案 0 :(得分:2)

实际上并不那么容易。旋转点在哪里?这对于固定大小的数字(如32位或64位整数)很容易,但对BigIntegers则不行。

但是......理论上,BigIntegers的大小是无限的,而且是两个补码(或者至少,它们表现得像它们一样,实际上它们通常是符号量级的)。所以正数(实际上)前面是无限数量的0位和负数,其中无限数量的1位。

因此向左旋转1实际上意味着向左移动1,如果数字为/是负数,则最低位设置为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);

这可能会快一点。