I have a scenario where I’m working with large integers (e.g. 160 bit), and am trying to create the biggest possible unsigned integer that can be represented with an n bit number at run time. The exact value of n isn’t known until the program has begun executing and read the value from a configuration file. So for example, n might be 160, or 128, or 192, etcetera…
Initially what I was thinking was something like:
BigInteger.valueOf((long)Math.pow(2, n));
but then I realized, the conversion to long that takes place sort of defeats the purpose, given that long is not comprised of enough bits in the first place to store the result. Any suggestions?
On the largest n-bit unsigned number
Let’s first take a look at what this number is, mathematically.
In an unsigned binary representation, the largest n-bit number would have all bits set to 1. Let’s take a look at some examples:
Note that this is analogous in decimal too. The largest 3 digit number is:
Thus, a subproblem of finding the largest n-bit unsigned number is computing 2n.
On computing powers of 2
Modern digital computers can compute powers of two efficiently, due to the following pattern:
That is, 2n is simply a number having its bit n set to 1, and everything else set to 0 (remember that bits are numbered with zero-based indexing).
Solution
Putting the above together, we get this simple solution using
BigIntegerfor our problem:If we were using
longinstead, then we can write something like this:There is no “set bit n” operation defined for
long, so traditionally bit shifting is used instead. In fact, aBigIntegeranalog of this shifting technique is also possible:See also
Additional
BigIntegertipsBigIntegerdoes have apowmethod to compute non-negative power of any arbitrary number. If you’re working in a modular ring, there are alsomodPowandmodInverse.You can individually
setBit,flipBitor justtestBit. You can get the overallbitCount, perform bitwiseandwith anotherBigInteger, andshiftLeft/shiftRight, etc.As bonus, you can also compute the
gcdor check if the numberisProbablePrime.ALWAYS remember that
BigInteger, likeString, is immutable. You can’t invoke a method on an instance, and expect that instance to be modified. Instead, always assign the result returned by the method to your variables.