This is probably pretty basic, but to save me an hour or so of grief can anyone tell me how you can work out the number of bits required to represent a given positive intege
Well, you can just count how many times you shift right before you're left with just zero:
int value = 11;
int count = 0;
while (value > 0) {
count++;
value = value >> 1;
}
I would like to add some other alternatives, just for the sake of completeness:
1 BigInteger.valueOf(i).bitLength()
Not very fast. Furthermore, BigInteger.bitLength()
it's bugged and unreliable (fixed in Java7), since when more than Integer.MAX_VALUE
bits are needed (freakishly high input number needed!! [such as 1 left-shifted Integer.MAX_VALUE
times, aka 2^Integer.MAX_VALUE
]) the result overflows and negative numbers appear for the next 2^(2*Integer.MAX_VALUE)-2^Integer.MAX_VALUE
numbers, which is a number so high your head could explode. Note that it is estimated the universe containes some 10^80 atoms; that number is 2^4G
(G
as in Giga, 1024*1024*1024
).
2
static int neededBits(int i)
{
assert i > 0;
int res;
int sh;
res = ((i > 0xFFFF) ? 1 : 0) << 4;
i >>= res;
sh = ((i > 0xFF) ? 1 : 0) << 3;
i >>= sh;
res |= sh;
sh = ((i > 0xF) ? 1 : 0) << 2;
i >>= sh;
res |= sh;
sh = ((i > 0x3) ? 1 : 0) << 1;
i >>= sh;
res |= sh;
res |= (i >> 1);
return res + 1;
}
A very fast solution, but still half as fast as ye olde 32 - Integer.numberOfLeadingZeros(i);
.
This is in C, but I suspect you could convert to Java fairly easily:
Find the log base 2 of an N-bit integer in O(lg(N)) operations
For non-negative values, probably the most direct answer is:
java.math.BigDecimal.valueOf(value).bitLength()
(For negative numbers it will give the bit length of one less than the absolute value, rather than infinity you'd expect from two's complement notation.)
My Java is a bit rusty, but the language-agnostic answer (if there is a "log2" function and a "floor" function available) would be:
numberOfBits = floor(log2(decimalNumber))+1
Assuming that "decimalNumber" is greater than 0. If it is 0, you just need 1 bit.
You can also do it like this, if you don't want to modify the original value.
unsigned int value = 11;
unsigned int count = 0;
if(value > 0)
{
for(int i=1;i<value;i*=2) // multiply by two => shift one to left
{
++count;
}
}
Note: Let the compiler worry about turning i*=2
into a bit shift operation to improve performance.
For the visual thinkers among us:
64 32 16 8 4 2 1
0 0 0 1 0 1 1 -> binary representation of decimal number 'value' = 11 (=1+2+8)
We start with i=1
at the right.
Then we keep multiplying by two, for as long as i < value
.
In the meanwhile, we keep track of how many bits we went to the left.
So in this example, as soon as i
reaches 16 the value is larger than 11, and thus we stop. And we will then have counted 4 bits: 1 *2 *2 *2 *2 = 16 (=2^4)
.
Careful with signed numbers. When dealing with signed numbers that may be positive or negative, you would first have to multiply the negative numbers by -1. Additionally, you would have to consider how you want to take the sign-bit into account.