0

What are the options to quickly list the 1's of a Java BigInteger? We can assume the BigInteger is positive, but it might be a rather large Java BigInteger with sparely distributed 1's. Nevertheless we would like to find them quickly. I would like to have an enumerator or iterator for the bit-positions of the 1's of a Java BigInteger.

xskxzr
  • 12,442
  • 12
  • 37
  • 77
  • Chai T. Rex's answer does what you want, but I am not sure if it is faster than simply testing each bit with `testBit()` in a loop (Henry's comment). You could test both and see which is faster or at least fast enough. If the 1 bits are pretty sparse, the `getLowestSetBit()` -- `clearBit()` method could be faster. – Rudy Velthuis Feb 04 '18 at 11:35

3 Answers3

1

You can use BigInteger's getLowestSetBit and clearBit methods. For example, to print them out:

public static final void printOneIndexes(BigInteger n) {
    while (!n.equals(BigInteger.ZERO)) {
        int i = n.getLowestSetBit();
        System.out.printf(" %d", i);
        n = n.clearBit(i);
    }
}
Chai T. Rex
  • 2,972
  • 1
  • 15
  • 33
0

Use .toString(radix) method. Like this: bigInteger.toString(2) and then check for ones in a string

Robert K.
  • 1,043
  • 1
  • 8
  • 20
  • 2
    Why would you convert to a string, when you can test the bits directly `BigInteger.testBit(int n)`? – Henry Feb 03 '18 at 09:50
  • @Ridcully the result would be the same as `bigInteger.bitCount()` which might be even easier to read and understand. – Henry Feb 03 '18 at 12:22
  • @Ridcully because this is not the question. OP wants the bit positions, not the number of them. – Henry Feb 03 '18 at 18:16
0

One can use getLowestSetBit(), but tests showed that the following is about 3-4 times as fast:

public static final void printOneIndexes(BigInteger n)
{
    for (int i = 0; i < n.bitLength(); i++)
    {
        if (n.testBit(i))
            System.out.printf(" %d", i);
    }
}

Of course, if you remove the printing, and store the results in a list, it can be much faster still.

I tested it with a BigInteger with only a few bits set, created by:

public static BigInteger makeSparseInt()
{
    BigInteger b = BigInteger.ZERO.setBit(1000000);

    Random r = new Random();

    for (int i = 0; i < 100; i++)
    {
        b = b.setBit(r.nextInt(1000000));
    }
    return b;
}
Rudy Velthuis
  • 28,387
  • 5
  • 46
  • 94