移动Java位集
我使用移动Java位集,java,bitset,bit-shift,Java,Bitset,Bit Shift,我使用java.util.BitSet来存储密集的位向量 我想实现一个将位右移1的操作,类似于int上的> 是否有一个库函数可以移位位集s 如果没有,还有比下面更好的方法吗 public static void logicalRightShift(BitSet bs) { for (int i = 0; (i = bs.nextSetBit(i)) >= 0;) { // i is the first bit in a run of set bits. // Set
java.util.BitSet
来存储密集的位向量
我想实现一个将位右移1的操作,类似于int上的>
是否有一个库函数可以移位位集
s
如果没有,还有比下面更好的方法吗
public static void logicalRightShift(BitSet bs) {
for (int i = 0; (i = bs.nextSetBit(i)) >= 0;) {
// i is the first bit in a run of set bits.
// Set any bit to the left of the run.
if (i != 0) { bs.set(i - 1); }
// Now i is the index of the bit after the end of the run.
i = bs.nextClearBit(i); // nextClearBit never returns -1.
// Clear the last bit of the run.
bs.clear(i - 1);
// 0000111100000...
// a b
// i starts off the loop at a, and ends the loop at b.
// The mutations change the run to
// 0001111000000...
}
}
另一种可能更有效的方法是使用基础的long[] 使用
bitset.toLongArray()
获取底层数据。相应地移动这些长度,然后通过BitSet.valueOf(long[])
创建一个新的位集。您必须非常小心地移动基础的长度,因为您必须在数组中的下一个长度上将低阶位移到高阶位
这应该允许您使用处理器上的本机位移位操作一次移动64位,而不是单独迭代每个位
编辑:根据路易斯·瓦瑟曼的评论。这仅在Java1.7API中可用。当我写它的时候,我没有意识到这一点。这应该可以做到:
BitSet shifted = bs.get(1, bs.length());
它将为您提供一个与原始位相同的位集,但没有最低位
编辑:
要将其推广到n
位
BitSet shifted = bs.get(n, Math.max(n, bs.length()));
您可以查看位集
toLongArray
和值(long[])
基本上获取
long
数组,移动long
s,并从移动的数组中构造一个新的位集。请找到位集“左移”的这个代码块
/**
*将位集向左移动。
*例如:0b10010(=18)=>0b100100(=36)(相当于乘以2)
*@param位集
*@返回移位位集
*/
公共静态位集leftShiftBitSet(位集位集){
最终长面罩=0x80000000000000L;
long[]沿=bitSet.toLongArray();
布尔进位=假;
对于(int i=0;i<沿长度;++i){
如果(携带){
进位=((沿[i]和maskOfCarry)!=0);
沿[i]方向,这些函数分别模拟>>运算符
/**
* Shifts a BitSet n digits to the left. For example, 0b0110101 with n=2 becomes 0b10101.
*
* @param bits
* @param n the shift distance.
* @return
*/
public static BitSet shiftLeft(BitSet bits, int n) {
if (n < 0)
throw new IllegalArgumentException("'n' must be >= 0");
if (n >= 64)
throw new IllegalArgumentException("'n' must be < 64");
long[] words = bits.toLongArray();
// Do the shift
for (int i = 0; i < words.length - 1; i++) {
words[i] >>>= n; // Shift current word
words[i] |= words[i + 1] << (64 - n); // Do the carry
}
words[words.length - 1] >>>= n; // shift [words.length-1] separately, since no carry
return BitSet.valueOf(words);
}
/**
* Shifts a BitSet n digits to the right. For example, 0b0110101 with n=2 becomes 0b000110101.
*
* @param bits
* @param n the shift distance.
* @return
*/
public static BitSet shiftRight(BitSet bits, int n) {
if (n < 0)
throw new IllegalArgumentException("'n' must be >= 0");
if (n >= 64)
throw new IllegalArgumentException("'n' must be < 64");
long[] words = bits.toLongArray();
// Expand array if there will be carry bits
if (words[words.length - 1] >>> (64 - n) > 0) {
long[] tmp = new long[words.length + 1];
System.arraycopy(words, 0, tmp, 0, words.length);
words = tmp;
}
// Do the shift
for (int i = words.length - 1; i > 0; i--) {
words[i] <<= n; // Shift current word
words[i] |= words[i - 1] >>> (64 - n); // Do the carry
}
words[0] <<= n; // shift [0] separately, since no carry
return BitSet.valueOf(words);
}
/**
*将位集n位向左移动。例如,n=2的0b0110101变为0b10101。
*
*@param位
*@param n移动距离。
*@返回
*/
公共静态位集移位(位集位,int n){
if(n<0)
抛出新的IllegalArgumentException('n'必须大于等于0”);
如果(n>=64)
抛出新的IllegalArgumentException('n'必须小于64”);
long[]字=位。toLongArray();
//轮班
for(int i=0;i>>>=n;//移位当前字
单词[i]|=单词[i+1]>>=n;//分别移位[words.length-1],因为没有进位
返回BitSet.valueOf(字);
}
/**
*将位集n位向右移动。例如,n=2的0b0110101变为0b000110101。
*
*@param位
*@param n移动距离。
*@返回
*/
公共静态位集移位触发器(位集位,int n){
if(n<0)
抛出新的IllegalArgumentException('n'必须大于等于0”);
如果(n>=64)
抛出新的IllegalArgumentException('n'必须小于64”);
long[]字=位。toLongArray();
//如果有进位,则展开数组
如果(字[words.length-1]>>>(64-n)>0){
long[]tmp=新长[words.length+1];
System.arraycopy(字,0,tmp,0,字.长度);
单词=tmp;
}
//轮班
对于(int i=words.length-1;i>0;i--){
单词[i]>(64-n);//进行进位
}
words[0]为了获得更好的性能,您可以扩展java.util.BitSet实现并避免不必要的数组复制。以下是实现(我基本上重用了Jeff Piersol实现):
package first.specific.structure;
导入java.lang.reflect.Field;
导入java.util.BitSet;
公共类BitSetMut扩展了BitSet{
私人长[]字;
私有静态字段wordsField;
静止的{
试一试{
wordsField=BitSet.class.getDeclaredField(“words”);
wordsField.setAccessible(true);
}捕获(无此字段例外){
抛出新的非法状态异常(e);
}
}
公共位setmut(最终整数regLength){
超级(regLength);
试一试{
words=(long[])wordsField.get(this);
}捕获(非法访问例外e){
抛出新的非法状态异常(e);
}
}
公共无效移位(整数n){
if(n<0)
抛出新的IllegalArgumentException('n'必须大于等于0”);
如果(n>=64)
抛出新的IllegalArgumentException('n'必须小于64”);
如果(words.length>0){
保证能力(n);
//轮班
对于(int i=words.length-1;i>0;i--){
单词[i]>(64-n);//进行进位
}
字[0]>n>0){
long[]tmp=新长[words.length+3];
System.arraycopy(字,0,tmp,0,字.长度);
单词=tmp;
试一试{
wordsField.set(这个,tmp);
}捕获(非法访问例外e){
抛出新的非法状态异常(e);
}
}
}
}
您可以使用biginger
而不是BitSet
biginger
已经有ShiftRight和ShiftLeft。使用java SE8,可以通过更简洁的方式实现:
BitSet b = new BitSet();
b.set(1, 3);
BitSet shifted = BitSet.valueOf(Arrays.stream(
b.toLongArray()).map(v -> v << 1).toArray());
位集b=新位集();
b、 组(1,3);
位集移位=位集.valueOf(Arrays.stream(
b、 get
上的[documentation](,int))映射(v->v)使我感到困惑。“返回一个新的位集,该位集由从索引(包含)到索引(独占)的位组成。”表示此中fromIndex
处的位映射到输出中的0
。@Mike。它的工作原理类似于String.substring(begin,end)
。请注意,此ca中的begin
package first.specific.structure;
import java.lang.reflect.Field;
import java.util.BitSet;
public class BitSetMut extends BitSet {
private long[] words;
private static Field wordsField;
static {
try {
wordsField = BitSet.class.getDeclaredField("words");
wordsField.setAccessible(true);
} catch (NoSuchFieldException e) {
throw new IllegalStateException(e);
}
}
public BitSetMut(final int regLength) {
super(regLength);
try {
words = (long[]) wordsField.get(this);
} catch (IllegalAccessException e) {
throw new IllegalStateException(e);
}
}
public void shiftRight(int n) {
if (n < 0)
throw new IllegalArgumentException("'n' must be >= 0");
if (n >= 64)
throw new IllegalArgumentException("'n' must be < 64");
if (words.length > 0) {
ensureCapacity(n);
// Do the shift
for (int i = words.length - 1; i > 0; i--) {
words[i] <<= n; // Shift current word
words[i] |= words[i - 1] >>> (64 - n); // Do the carry
}
words[0] <<= n; // shift [0] separately, since no carry
// recalculateWordInUse() is unnecessary
}
}
private void ensureCapacity(final int n) {
if (words[words.length - 1] >>> n > 0) {
long[] tmp = new long[words.length + 3];
System.arraycopy(words, 0, tmp, 0, words.length);
words = tmp;
try {
wordsField.set(this, tmp);
} catch (IllegalAccessException e) {
throw new IllegalStateException(e);
}
}
}
}
BitSet b = new BitSet();
b.set(1, 3);
BitSet shifted = BitSet.valueOf(Arrays.stream(
b.toLongArray()).map(v -> v << 1).toArray());