我有一个下表的函数。
| 输入:e|输出:1 << e|
| - -----|- -----|
| 0
| 1
|
| 1
| 2
|
| ……|……|
| 31
| -2147483648
|
static int value(int exponent) {
return 1 << exponent;
}
现在,如何从value
中获取exponent
?
我尝试了下面的代码,它在-2147483648
的最后一个条目失败。
int exponent(int value) {
return (int) (Math.log(value) / Math.log(2)); // -> NaN / Math.log(2)
}
我把它修好了。
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));
}
有没有更好的/合适的方法来做这件事?
2条答案
按热度按时间zdwk9cvp1#
你可以使用
Integer.numberOfLeadingZeros
来实现。根据JavaDoc:请注意,此方法与以2为底的对数密切相关。对于所有正整数值x:
要实现
exponent
方法,只需复制JavaDoc的建议:请注意,在您的情况下,这也适用于负数,即使没有为非正数定义对数:对于所有负数,由于它们在二的补码中的表示,最左边的位将是1。因此,对于任何负值,
Integer.numberOfLeadingZeros
返回0,因此exponent
方法计算31
。另外请注意,如果
value == 0
,则exponent
返回-1
,这是您可能需要注意的情况。例如,您可以抛出IllegalArgumentException
,因为0
的对数未定义。nzkunb0c2#
使用
Integer.numberOfLeadingZeros()
作为 * Alex R * 在他们的答案中建议的,对于正输入是完全可以的,但是对于任何负数都可以将被评估为
31
,因为每个负数的第一位是1
。这个结果(
31
的指数)对于-2147483648
是有意义的,因为2^31 = 2147483648(正如 * Alex R * 在他们的回答中所说的那样),但对于-1
,-16
,-256
等没有意义。要获得负输入的正确结果,您需要使用给定输入的绝对值。
为了处理给定值为
Integer.MIN_VALUE
(在int
类型中没有正等价值,因为Integer.MAX_VALUE
小1)而不需要额外检查的情况,可以使用long
。下面是使用按位逻辑实现它的方法之一:
简单演示:
输出: