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:
1
(2)= 1 =
21 - 1
11
(2)= 3 =
22 - 1
111
(2)= 7 =
23 - 1
:
1………1
(2)=
2n -1
n
Note that this is analogous in decimal too. The largest 3 digit number is:
10
3- 1 = 1000 - 1 = 999
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:
20= 1
(2)
21= 10
(2)
22= 100
(2)
23= 1000
(2)
:
2n= 10………0
(2)
n
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 BigInteger
for our problem:
final int N = 5;
BigInteger twoToN = BigInteger.ZERO.setBit(N);
BigInteger maxNbits = twoToN.subtract(BigInteger.ONE);
System.out.println(maxNbits); // 31
If we were using long
instead, then we can write something like this:
// for 64-bit signed long version, N < 64
System.out.println(
(1L << N) - 1
); // 31
There is no "set bit n" operation defined for long
, so traditionally bit shifting is used instead. In fact, a BigInteger
analog of this shifting technique is also possible:
System.out.println(
BigInteger.ONE.shiftLeft(N).subtract(BigInteger.ONE)
); // 31
See also
Additional BigInteger
tips
BigInteger
does have a pow
method to compute non-negative power of any arbitrary number. If you're working in a modular ring, there are also modPow
and modInverse
.
You can individually setBit
, flipBit
or just testBit
. You can get the overall bitCount
, perform bitwise and
with another BigInteger
, and shiftLeft
/shiftRight
, etc.
As bonus, you can also compute the gcd
or check if the number isProbablePrime
.
ALWAYS remember that BigInteger
, like String
, 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.