Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java LeetCode 231:查找给定数字是否为2的幂的问题_Java_Algorithm_Math - Fatal编程技术网

Java LeetCode 231:查找给定数字是否为2的幂的问题

Java LeetCode 231:查找给定数字是否为2的幂的问题,java,algorithm,math,Java,Algorithm,Math,我想用数学的方法,而不是按位的方法,来确定一个给定的数字是否是a。这是我的密码: private static double logBaseTwo(final double x) { return Math.log(x) / Math.log(2); } private static double roundToNearestHundredThousandth(final double x) { return Math.round(x * 100000.0) / 100000.

我想用数学的方法,而不是按位的方法,来确定一个给定的数字是否是a。这是我的密码:

private static double logBaseTwo(final double x) {
    return Math.log(x) / Math.log(2);
}

private static double roundToNearestHundredThousandth(final double x) {
    return Math.round(x * 100000.0) / 100000.0;
}

private static boolean isInteger(final double x) {
    return (int)(Math.ceil(x)) == (int)(Math.floor(x));
}

public static boolean isPowerOfTwo(final int n) {
    return isInteger(roundToNearestHundredThousandth(logBaseTwo(n)));
}

对于某些数字,例如
524287
,它错误地返回
true
。为什么会这样?

这是一段非常糟糕的代码,我不知道你想做什么。您似乎试图检查
n
log
base
2
是否为整数。相反,我将编写一个循环:

while (n>1) {
   m = (n/2) * 2
   if (n!=m){
       return false;
     }
   n /=2;
}
return true;

解决方案似乎比应该的复杂。我没有得到
100000d
零件-在转换到天花板时可能会导致问题

这是适用于所有情况的简单解决方案:

public静态布尔值isPowerOfTwo(int n){
返回Math.ceil(Math.log(n)/Math.log(2))==Math.floor(Math.log(n)/Math.log(2));
}

双精度和浮点数分别具有64位和32位精度。这意味着他们最多只能持有18446744073709551616个唯一的号码。这是很多数字,但不是无限的。在某一点上(事实上,该点大约发生在2^52),作为18446744073709551616可表示数字的一部分的任何两个数字之间的“间隙”将大于1.000。类似的规则也适用于小数字。Math.log不执行基于
的双重数学

其次,INT也同样有限。它们最多可以容纳4294967296个不同的号码。对于整数来说,它要简单得多:整数可以从-2147483648保存到2147483647。如果您尝试将1添加到2147483647中,您将得到-2147483648(它会自动环绕)。很有可能你在尝试将如此大的数字(你的两倍乘以10000d)先转换成整数时遇到了这种情况

请注意,
?true:false(与问题的原始版本一样)实际上是完全无用的。问号左边的东西必须是布尔值,布尔值已经是真或假了,这就是它们的本质


有关解决此问题的更简单方法,请参见其他答案。当然,最简单的解决方案是简单地计算数字中的位。如果正好是1位,则是2的幂。如果它是0位,那么,你告诉我,如果你认为“0”是一个2的幂:

最初我在计算中使用了<代码>数学> log < /代码>。我切换到
Math.log10
,问题就解决了。尽管从数学上讲,基B的任何
logB
都应该可以工作,但浮点数学的性质可能是不可预测的

试试这个

public static boolean isPowerOfTwo(int n) {
   return  n > 0 && Integer.highestOneBit(n) == Integer.lowestOneBit(n);
}
如果你喜欢使用日志,你可以这样做

public static boolean isPowerOfTwo(int n) {
   return n > 0 && (Math.log10(n)/Math.log10(2))%1 == 0;
}



您的代码失败,因为您可能需要更高的精度来捕获BIG_NUMBER和BIG_NUMBER+1日志之间的差异

按位方式确实是最好的,但如果您真的只想使用“mathy”运算,那么您最好的方法可能是:

public static boolean isPowerOfTwo(final int n) {
   int exp = (int)Math.round(logBaseTwo(n));
   int test = (int)Math.round(Math.pow(2.0,exp));
   return test == n;
}

此解决方案不需要任何超精细精度,适用于所有正整数。

我希望您认识到,使用逐位方法是一种数学方法。他们认为你建议的方式过于复杂,在计算机上工作有困难。@ruakh编辑问题使答案无效是错误的。请把三元运算符放回去。@NomadMaker:问题是为什么代码不起作用。正如rzwitserloot所指出的,三元运算符不影响代码的行为;所以这与问题无关。@ruakh它混淆了对答案的理解。它应该留在问题中,或者在问题中添加一条注释,说明原始代码(…)已被此代码(…)替换。@NomadMaker:我现在编辑了该答案,以澄清它所指的内容。+1。精确到十万分之一正是问题所在:log₂ 524287≈ 18.999997正在四舍五入到19.0,这是一个整数。因此,在某种意义上,OP的代码是524287到524288的四舍五入,这是二的幂。(顺便说一句,欢迎使用堆栈溢出!)事实上,很抱歉,这个答案是不正确的:这段代码错误地为
536870912
(至少在我的系统上)返回
false
,因为浮点结果是
29.00000000000000 4
,而不是
29
。这是我的错误,我不确定我是如何忽略它的。使用Math.log并没有消除数学错误,所以我切换到Math.log10,它成功了。这仍然困扰着我,因为在分子和分母中使用任何基的
log
。但这是数学,我们正在使用IEEE754,因此即使使用ceil和floor方法也无法消除计算中的微小误差。