如何在位集JAVA中左右移动位?

如何在位集JAVA中左右移动位?,java,bit-manipulation,bit-shift,bitset,Java,Bit Manipulation,Bit Shift,Bitset,我有一个位数为100000的位集。我希望尽可能高效地将其向右和向左移动。我猜BitSet类中没有移位位的函数,所以我尝试使用toLongArray()将它们转换为长数组,但正如预期的那样,它会产生溢出 我发现的一个临时解决方案是将位集转换为biginger,然后将biginger移位,然后将biginger转换回位集,但这非常缓慢 因此,我的问题是: 有没有更好的方法来移位一个位集(移位我指的是左移位和右移位) 当我将位数大于64的位集转换为长数组时,数组中会出现负数。当位集只能表示1个数字的位

我有一个位数为100000的位集。我希望尽可能高效地将其向右和向左移动。我猜BitSet类中没有移位位的函数,所以我尝试使用
toLongArray()
将它们转换为长数组,但正如预期的那样,它会产生溢出

我发现的一个临时解决方案是将位集转换为biginger,然后将biginger移位,然后将biginger转换回位集,但这非常缓慢

因此,我的问题是:

  • 有没有更好的方法来移位一个位集(移位我指的是左移位和右移位)
  • 当我将位数大于64的位集转换为长数组时,数组中会出现负数。当位集只能表示1个数字的位时,为什么首先要有一个函数
    toLongArray()
    。如果我错了,请纠正我
  • 下面是使用BigInteger的代码

    公共静态位集toBitSet(biginger val){
    if(val.signum()<0)
    抛出新的IllegalArgumentException(“负值:+val”);
    返回BitSet.valueOf(反向(val.toByteArray());
    }
    静态字节[]反向(字节[]字节){
    对于(int i=0;i
    PS:我找到的所有答案都是关于位数的 当我将位数大于64的位集转换为长数组时,数组中会出现负数

    负元素非常好,这只是使用
    长的所有64位的结果,因此包括符号位。只要你能预料到,这并不重要。基本上,它只是在打印带有签名的解释时看起来很奇怪,否则这不是一件坏事

    因此,我尝试使用
    toLongArray()
    将它们转换为长数组,但正如预期的那样,它会产生溢出

    这是一个合理的实施策略,所以让我们来解决它。我猜你在没有处理“进位”的情况下单独移动了每个元素。左移位需要做的是将一个元素的顶部位放入下一个元素的底部位。对于右移来说,情况正好相反。例如,对于小于或等于63的
    n
    (未测试)

    静态位集移位触发器(位集位,int n){
    long[]原始=位。toLongArray();
    长进位=0;
    对于(int i=raw.length-1;i>=0;i--){
    长进位=原始进位[i]>>n)|进位;
    进位=新进位;
    }
    返回BitSet.valueOf(原始);
    }
    
    如果
    n
    可以是64或更大,则将整个元素移动到不同位置会带来额外的复杂性


    向左移动会带来额外的复杂性,即结果集可能比输入更大(不是设置更多的位,而是物理上更大,需要更长的数组)。

    如果您需要尽可能有效的左移,可以使用
    列表来代替,例如,
    LinkedList
    应该是最有效的移位数据结构,因为您可以通过在
    O(1)
    @Robert yes中插入/删除元素来执行移位操作,但我还想执行and、or、xor等操作。比特集内置了对它们的支持,这就是我选择它的原因。为什么你认为获取负长值是个问题?如果可以使用长负值的所有64位,则只需使用长on位级别,不要试图将其解释为值。顺便说一句:查看位集的实现,您可以看到它在内部使用
    long[]
    来存储位。因此,通过调用
    toLongArray()
    您只需获得内部表示的副本。@Robert。这是一个问题,因为我认为应该只返回一个值。但正如您所说,内部实现使用
    long[]
    ,那么我想在溢出的情况下获得一个填充了-ve值的数组是有意义的。
    static BitSet shiftRight(BitSet bits, int n) {
        long[] raw = bits.toLongArray();
        long carry = 0;
        for (int i = raw.length - 1; i >= 0; i--) {
            long newcarry = raw[i] << -n;
            raw[i] = (raw[i] >>> n) | carry;
            carry = newcarry;
        }
        return BitSet.valueOf(raw);
    }