在Java中,查找最左/最右未设置位的索引最有效的方法是什么?

在Java中,查找最左/最右未设置位的索引最有效的方法是什么?,java,bit-manipulation,bitwise-operators,Java,Bit Manipulation,Bitwise Operators,假设我们有intx=371,即二进制格式101110011。我想找到最左边未设置位的索引(在本例中为7),以及最右边未设置位的索引(在本例中为2)。最有效的方法是什么 以下是我所拥有的: public class BitOperatons { public static int setBit(int x, int i) { int y = x | (1 << i); return y; } public static boo

假设我们有
intx=371
,即二进制格式
101110011
。我想找到最左边未设置位的索引(在本例中为7),以及最右边未设置位的索引(在本例中为2)。最有效的方法是什么

以下是我所拥有的:

public class BitOperatons {

    public static int setBit(int x, int i) {
        int y = x | (1 << i);
        return y;
    }

    public static boolean isBitSet(int x, int i) {
        int y = setBit(0, i);
        return y == (x & y);
    }    

    public static int findLeftMostSetBit(int x) {
        for (int i = 31; i >= 0; i--) {
            if (isBitSet(x, i))
                return i;
        }
        return -1;
    }

    public static int findRightMostUnsetBit(int x) {
        for (int i = 0; i <= 31; i++) {
            if (! isBitSet(x, i))
                return i;
        }
        return -1;
    }

    public static int findLeftMostUnsetBit(int x) {
        int k = findLeftMostSetBit(x);
        for (int i = k; i >= 0; i--) {
            if (! isBitSet(x, i))
                return i;
        }
        return -1;
    }

    public static1+ void main(String[] args) {
        int x = 
            (1 << 0) |
            (1 << 1) |
            (1 << 4) |
            (1 << 5) |
            (1 << 6) |
            (1 << 8);
        System.out.println(findLeftMostUnsetBit(x));
        System.out.println(findRightMostUnsetBit(x));
    }

}
公共类位运算符{
公共静态整数setBit(整数x,整数i){
int y=x |(1=0;i--){
if(isBitSet(x,i))
返回i;
}
返回-1;
}
公共静态int findrightmostunesbit(int x){
对于(int i=0;i=0;i--){
if(!isBitSet(x,i))
返回i;
}
返回-1;
}
公共static1+void main(字符串[]args){
整数x=

(1Integer类中有可用的方法

Integer.numberOfTrailingZeros(Integer.lowstonebit(~yourValue))
将用于最低的未设置位,对于最高的未设置位,这有点棘手,因为我们首先必须确定最高的设置位

int leadingZeroBits = Integer.numberOfLeadingZeros(Integer.highestOneBit(yourValue));
result = Integer.
       numberOfTrailingZeros(Integer.highestOneBit((~yourValue)<<leadingZeroBits)
      -leadingZeroBits;`
int leadingZeroBits=Integer.numberOfLeadingZeros(Integer.highestOneBit(yourValue));
结果=整数。

numberOfTrailingZeros(Integer.highestOneBit(~yourValue)下面是Integer.numberOfLeadingZeros的源代码。正如前面所指出的,它取自HD(小亨利·s·沃伦的《黑客的喜悦》)

其主要思想是使用二进制搜索,而不是一个接一个地迭代位。如果你对位旋转感兴趣,请查阅这本书。这是一件很棒的艺术作品

public static int numberOfLeadingZeros(int i) {
    // HD, Figure 5-6
    if (i == 0)
        return 32;
    int n = 1;
    if (i >>> 16 == 0) { n += 16; i <<= 16; }
    if (i >>> 24 == 0) { n +=  8; i <<=  8; }
    if (i >>> 28 == 0) { n +=  4; i <<=  4; }
    if (i >>> 30 == 0) { n +=  2; i <<=  2; }
    n -= i >>> 31;
    return n;
}
public static int numberofleadingzero(int i){
//HD,图5-6
如果(i==0)
返回32;
int n=1;
如果(i>>>16==0){n+=16;i>24==0){n+=8;i>28==0){n+=4;i>30==0){n+=2;i>31;
返回n;
}

不可能比线性更好。@toto,这不是真的,doh忘记了,看看黑客的喜悦5-3(例如)(前导零,它是Integer.class的一部分)@bestsss,好吧,如果你是指弗洛洛建议的机器指令。如果你知道一个次线性算法,我想知道。@toto,不,它不是汇编程序或CPU提供的指令。它是二进制搜索,而不是线性:)。认真地找一本《黑客的喜悦》(书)并检查它。我将发布如何做前导零部分。我相信即使这样也会有一些内容。@bestsss是的,我现在正在考虑。我想写它作为答案。谢谢。使用Java API更好。(编辑:只检查了
Integer.numberOfTrailingZeros的代码,这是二进制搜索。)Sun中实现的代码(Oracle)库稍有不同,但相当。@bestsss:
numberOfLeadingZeros
是我的
findLeftMostSetBit
的一个更有效的实现。但是,我不知道如何使用它来回答我的问题,那就是找到最左/最右未设置位的索引。如果我们有
0000000000000000000000000000 101110011
,那么我想找到最左边未设置位的索引,是7,最右边未设置位的索引,是2。你会怎么做?(感谢你推荐小亨利·s·沃伦的《黑客的喜悦》:这似乎是一本非常有趣的书,我会把它放在我的愿望列表中:))@MarcoS,看看flolo的答案,你会发现这个答案主要是针对toto在评论中的评论。Paul Cacker的评论还包含一个非常有用的C语言集合(也可以移植到java)比特旋转黑客。@bestsss:我明白了!…所以我应该选择你和弗洛洛的帖子作为答案,但我不能。所以,我会选择弗洛洛的作为答案,但仍然支持你的答案。@MarcoS,我把它作为社区维基是有原因的。关于高清,如果你对比特旋转感兴趣的话,它仍然是想法的主要来源,是fasc使用的比特之舞当我还是个孩子的时候(做汇编)嗯,实际上,在可能的情况下,intrinsic看起来像CPU指令。