Java中的整数用于哪个位

时间:2012-05-09 10:18:44

标签: java bit-manipulation

我编写了这段代码来检查Java中Integer(如果用二进制表示)的哪些位是打开的:

public static List<String> list(int val)
{
    List<String> dummyList = new ArrayList<String>();

    int bit = 1;
    int x;

    for(int i=0; i<32; i++)
    {
        x = bit;
        if((x&val)!=0)
            dummyList.add(String.valueOf(i+1));
        bit = bit << 1;
    }

    return dummyList;
}

以上编写的代码工作正常。但是它有一个运行32次的循环(在Java整数中是32位长)。我想尽量减少这种复杂性。请分享更好的解决方案。提前谢谢。

5 个答案:

答案 0 :(得分:1)

您可以使用位掩码来尝试减少循环次数。您添加了一些操作,但可能会执行一半的循环:

public static List<String> list(int val) {
    List<String> dummyList = new ArrayList<String>();
    int loop = 32;

    // Mask the 16 MSB if all are zero only loop on the 16 LSB
    if((val & 0xFFFF0000) == 0){
        loop = 16;
    }

    int bit = 1;
    int x;

    for (int i = 0; i < loop; i++) {
        x = bit;
        if ((x & val) != 0) {
            dummyList.add(String.valueOf(i + 1));
        }
        bit <<= 1;
    }

    return dummyList;
}

这可能会增加时间,具体取决于进来的数据。

您也可以通过一次做两位来减少一半的循环:

public static List<String> list(int val) {
    List<String> dummyList = new ArrayList<String>();

    int bit = 3;
    int x;

    for (int i = 0; i < 32; i += 2) {
        x = (bit & val);
        switch (x) {
            case 1:
                dummyList.add(String.valueOf(i + 1));
                break;
            case 2:
                dummyList.add(String.valueOf(i+2));
                break;
            case 3:
                dummyList.add(String.valueOf(i+1));
                dummyList.add(String.valueOf(i+2));
                break;
            default:
        }
        val >>= 2;
    }

    return dummyList;
}

答案 1 :(得分:0)

复杂度为O(1),因此没有太多“最小化”。

你的代码没问题......这里稍微重构一下。

public static List<String> list(int val) {
    List<String> dummyList = new ArrayList<String>();
    for (int i = 0; i < 32; i++)
        if ((1 << i & val) != 0)
            dummyList.add("" + (i+1));
    return dummyList;
}

顺便问一下,您考虑过使用BitSet吗?

答案 2 :(得分:0)

32个循环听起来很适合这个应用程序。如果要更快地收集数字,可以使用StringBuffer而不是List。

public static String list(int val)
{
    StringBuffer dummyList = new StringBuffer();

    int bit = 1;
    int x;

    for(int i=0; i<32; i++)
    {
        x = bit;
        dummyList.append((x&val) ? '1' : '0' );
        bit = bit << 1;
    }

    return dummyList.toString();
}

答案 3 :(得分:0)

改进O(1)代码似乎微不足道,但这段代码略有改进:

public static List<String> list(int val) {
    List<String> dummyList = new ArrayList<String>();
    for (int i=0; val!=0 && i<32; ++i){
        if ((1 << i & val) != 0) {
            dummyList.add("" + (i+1));
            val &= val -1;  // unset the last set bit (current bit)
        }                   // causes loop to end early when all bits are counted
    }
    return dummyList;

而不是进行所有32位比较,此代码将在最后一位计数后立即结束。对于使用1稀疏填充的整数来说效率要高得多,对于人口密集的整数来说效率也不低。

答案 4 :(得分:0)

由于您知道整数的确切长度,我建议您改用bool[]。尽管如此,你对复杂性无能为力。它的速度和它一样快,JIT可能会打开这段代码的循环。

public static bool[] list(int val)
{
    bool[] a = new bool[32];
    for(int i=0; i<32; i++)
    {
        a[i] = ((1 << i) & val) != 0;
    }
    return a;
}