I have a function of the following table.
input: e | output: 1 << e |
---|---|
0 |
1 |
1 |
2 |
... | ... |
31 |
-2147483648 |
static int value(int exponent) {
return 1 << exponent;
}
Now, how can I get the exponent
from a value
?
I tried the following code and it fails for the last entry of -2147483648
.
int exponent(int value) {
return (int) (Math.log(value) / Math.log(2)); // -> NaN / Math.log(2)
}
And I managed to fix it like this.
int exponent(int value) {
if (value == Integer.MIN_VALUE) {
return (int) (Math.log(value - 1) / Math.log(2)) + 1;
}
return (int) (Math.log(value) / Math.log(2));
}
Is there any better/proper way to do this?
You can use Integer.numberOfLeadingZeros
for that. According to its JavaDoc:
Note that this method is closely related to the logarithm base 2. For all positive int values x:
floor(log2(x)) = 31 - numberOfLeadingZeros(x) ceil(log2(x)) = 32 - numberOfLeadingZeros(x - 1)
To implement your exponent
method, simply copy what the JavaDoc suggests:
int exponent(int value) {
return 31 - Integer.numberOfLeadingZeros(value);
}
Note that this also works for negative numbers in your case, even though the logarithm is not defined for non-positive numbers: For all negative numbers, the left-most bit will be 1 due to their representation in the two's complement. Therefore, for any negative value, Integer.numberOfLeadingZeros
returns 0, and hence your exponent
method calculates 31
.
Also note, that if value == 0
, then exponent
returns -1
which is a case you might want to take care of. For example, you could throw an IllegalArgumentException
since the logarithm is undefined for 0
.