Java中的快速按位操作

时间:2015-01-19 00:55:09

标签: java optimization bitwise-operators bitset

我正在尝试创建一个快速生成特定序列的程序。

序列通过迭代给出,如下:

new = old + 1 + (-1*(old reversed))

示例:

old = [1]
new = [1]+[1]+[-1] = [1, 1, -1]

old = [1, 1, -1]
new = [1, 1, -1] + [1] + [1, -1, -1] = [1, 1, -1, 1, 1, -1, -1]

我希望这个尽可能快,我想由于序列只包含-1或1,我可以使用按位运算,让每个位代表truefalse然后,我可以将其映射到-11

然后我最终得到一系列位,我可以使用按位运算来操作。我有一个自定义类,它创建一个long[],然后将这些位组合成64位。

一切正常,我得到了正确的答案,但这个解决方案要比使用byte[]数组和循环槽慢得多。

最耗时的功能是反转位的顺序,并反转每一位。

现在看起来像:

//this function is inside the custom class I defined
public void set(int n, int d) { //set bit n as the inverse value of bit d
    storage[n/64] ^= ~(storage[ind/64] & (1L << ind)) << (n-ind);
}

//sequence is an instance of my custom class 
//the length of the sequence is sequenceLength 
for (int i = 1; i < sequenceLength; i++) {
    sequence.set(sequenceLength+i, sequenceLength-i);
}

有什么方法可以提高性能吗?我对按位操作很新。

编辑:这是包含所有相关方法的自定义类。

public class Dragon3 {

private FastStorage dragon;
private short[] xpos;
private short[] ypos;

public Dragon3(int n) {
    dragon = new FastStorage((int)Math.pow(2,n+1)-1);
    dragon.setSize(1);
    for (int i = 0; i < n; i++) {
        iterate(dragon);
    }

}

public class FastStorage {
    private long[] storage;
    private int size;

    public FastStorage(int n) {
        storage = new long[(n-1)/64+1];
        size = n;
    }
    public int getSize() {
        return size;
    }
    public void setSize(int n) {
        size = n;
    }
    public void set(int n, int ind) {
        storage[n/64] ^= (~storage[ind/64] & (1L << ind)) << (n-ind);
    }
    public long getInv(int n) {
        return ~(storage[n/64]) & (1L << n);            
    }

public void iterate(FastStorage drag) {
    int dragLength = drag.getSize();
    drag.setSize(2*dragLength+1);
    //drag.toggle(dragLength);
    for (int i = 1; i < dragLength+1; i++) {
        drag.set2(dragLength+i, dragLength-i);
        //drag.set(dragLength+i, drag.getInv(dragLength-i));
    }
}

public static void main(String[] args) {
    Dragon3 instance = new Dragon3(Integer.valueOf(args[0]));
}

}

2 个答案:

答案 0 :(得分:2)

你没有要求它,但你的序列有一个直接的公式:

public static void main(String[] args) {
    for( int n=1 ; n<=15 ; n++ ){
        int fold = 1 - ((n/(n&-n))&2);
        System.out.print(" " + fold);
    }
    System.out.println();
}

答案 1 :(得分:0)

您可以尝试使用BitSet,但它通常会跟踪设置的位,因此您可能需要跟踪您感兴趣的位数:

public static void main(String[] args) {
    BitSet bitSet = new BitSet();
    bitSet.set(0,true);
    bitSet.set(1, true);
    bitSet.set(2, false);

    final int length = 3;
    printBitSet(bitSet, length);

    BitSet newBitSet = new BitSet(length * 2 + 1);
    for (int i = 0; i <length; i++) {
        newBitSet.set(i, bitSet.get(i));
    }
    newBitSet.set(length, true);
    for (int i = 0; i < length; i++) {
        newBitSet.set(length + i + 1, !bitSet.get(length - i - 1));
    }
    printBitSet(newBitSet, 2*length +1);
}
private static void printBitSet(BitSet bitSet, int length) {
    for (int i = 0; i < length; i++) {
        System.out.print(" " +( bitSet.get(i) ? "1" : "-1"));
    }
    System.out.println();
}