如何找到比给定数量少2的最大功率

时间:2013-06-29 10:05:24

标签: java algorithm

我需要找到比给定数字少2的最大功率 我卡住了,找不到任何解决方案。

代码:

public class MathPow {
   public int largestPowerOf2 (int n) {
        int res = 2;        
        while (res < n) {
            res =(int) Math.pow(res, 2);
        }
        return res;
   }
}

这不能正常工作。

测试输出:

Arguments Actual Expected
-------------------------
9         16     8       
100       256    64      
1000      65536  512     
64        256    32      

如何解决这个问题?

20 个答案:

答案 0 :(得分:40)

Integer.highestOneBit(n-1);

n <= 1对于{{1}}这个问题并没有多大意义。该范围内的操作留给感兴趣的读者。

这是Hacker's Delight中的一个很好的比特缠绕算法集合。

答案 1 :(得分:11)

res =(int)Math.pow(res, 2);更改为res *= 2;这将返回大于res的下一个2的幂。
因此,您所寻找的最终结果将在片刻结束后最终为res / 2

为了防止代码溢出int值空间,你应该/可以将res的类型更改为double / long,任何可以保存高于int的值。最后你必须投一次。

答案 2 :(得分:11)

您可以使用此bit hack

v--;
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
v++;
v >>= 1;

答案 3 :(得分:9)

为什么不使用日志?

public int largestPowerOf2(int n) {
    return (int)Math.pow(2, Math.floor(Math.log(n) / Math.log(2));
}

log(n) / log(2)告诉您2进入数字的次数。通过取得它的底线,得到四舍五入的整数值。

答案 4 :(得分:7)

Integer中的一个很好的功能很有用,numberOfLeadingZeros

有了它,你可以做到

0x80000000 >>> Integer.numberOfLeadingZeros(n - 1);

n为0或1时,哪些奇怪的事情,但对于那些输入,没有明确定义的“2的最高功率小于n”。

编辑:this answer甚至更好

答案 5 :(得分:6)

你可以消除n中的最低有效位,直到n是2的幂。你可以使用n和n-1的按位运算符AND,这将消除n中的最低有效位,直到n为幂2.如果最初的n是2的幂,那么你所要做的就是将n减少1。

public class MathPow{
   public int largestPowerOf2(int n){
      if((n & n-1) == 0){ //this checks if n is a power of 2
         n--; //Since n is a power of 2 we have to subtract 1
      }
      while((n & n-1) != 0){ //the while will keep on going until n is a power of 2, in which case n will only have 1 bit on which is the maximum power of 2 less than n. You could eliminate the != 0 but just for clarity I left it in
         n = n & n-1; //we will then perform the bitwise operation AND with n and n-1 to eliminate the least significant bit of n 
      }
      return n;
   }
}

<强> 说明:

当你有一个数n(不是2的幂)时,小于n的2的最大幂总是n中的最高位。如果数字n是2的幂,则小于n的2的最大幂是n中唯一的位之前的位。

例如,如果我们有8(其为2到3次幂),则其二进制表示为1 0 00,粗体0将是n之前的2的最大幂。既然我们知道二进制中的每个数字代表2的幂,那么如果我们将n作为2的幂的数,那么2的最大幂小于n将是2之前的2的幂,这将是位在n。中唯一的位之前。

对于数字n,这不是2的幂并且不是0,我们知道在二进制表示中n将具有各种位,这些位将仅表示2的各种幂的总和,最重要的其中最重要的一点。然后我们可以推断出n只是最重要的位加上其他一些位。由于n以一定长度的比特表示,而最高有效位是2的最高功率,我们可以用该比特数表示,但它也是我们用这么多比特表示的最低数,那么我们可以得出结论最高有效位是低于n的2的最高功率,因为​​如果我们添加另一位来表示2的下一个幂,我们将具有大于n的2的幂。

<强> 实施例

例如,如果我们有168(二进制为10101000),则while需要168并减去1,即167(二进制为10100111)。然后我们将对两个数字进行按位AND。 示例:

  10101000
& 10100111
------------
  10100000

我们现在有二进制数10100000.如果我们从它中减去1并且我们在两个数字上使用按位AND,我们得到10000000这是128,这是2的7的幂。

示例:

  10100000
& 10011111
-------------
  10000000

如果n原来是2的幂,那么我们必须从n中减去1。例如,如果n是16,即二进制10000,我们将减去1,这将留下15,二进制为1111,并将它存储在n(这就是if)。然后我们进入while,它使用n和n-1进行按位运算符AND,它将是15(在二进制1111中)&amp; 14(二进制1110)。

示例:

  1111
& 1110
--------
  1110

现在我们剩下14.然后我们用n和n-1执行按位AND,这是14(二进制1110)&amp; 13(二进制1101)。

示例:

  1110
& 1101
---------
  1100

现在我们有12个,我们只需要消除最后一个最低位。然后,我们再对n和n-1执行按位AND,即12(二进制1100)和11(二进制1011)。

示例

  1100
& 1011
--------
  1000

我们最终留下了8,这是2小于16的最大力量。

答案 6 :(得分:3)

您每次都在平仓 res ,这意味着您计算2^2^2^2而不是2^k
将您的评估更改为以下内容:

int res = 2;
while (res * 2 < n) {
    res *= 2;
}

更新:

当然,您需要检查 int 的溢出,在这种情况下检查

  

while(res&lt; =(n - 1)/ 2)

似乎好多了。

答案 7 :(得分:3)

public class MathPow
{
   public int largestPowerOf2 (int n)
   {
        int res = 2;        
        while (res < n) {
                res =res*2;
        }

        return res;
   }
}

答案 8 :(得分:3)

这是我为此目的编写的递归位移方法:

public static int nextPowDown(int x, int z) {
    if (x == 1)
        return z;
    return nextPowDown(x >> 1, z << 1);
} 

或更短的定义:

public static int nextPowTailRec(int x) {
    return x <= 2 ? x : nextPowTailRec(x >> 1) << 1;
}

因此,在您的main方法中,让z参数始终等于1。很可惜默认参数在这里不可用:

System.out.println(nextPowDown(60, 1));                // prints 32
System.out.println(nextPowDown(24412, 1));             // prints 16384
System.out.println(nextPowDown(Integer.MAX_VALUE, 1)); // prints 1073741824

答案 9 :(得分:2)

从左到右找到第一个设置位,并使所有其他设置位为0。

如果只有1个设置位,则向右移动一次。

答案 10 :(得分:1)

public class MathPow
{
   public int largestPowerOf2(int n)
   {
        int res = 1;        
        while (res <= (n-1)/2)
        {
            res = res * 2;
        }

        return res;
   }
}

答案 11 :(得分:1)

如果数字是整数,您可以随时将其更改为二进制,然后找出位数。

n = (x>>>0).toString(2).length-1

答案 12 :(得分:0)

如果数字是2的幂,那么答案是显而易见的。 (只是位移)如果不好那么它也可以通过位移来实现。

以二进制表示法查找给定数字的长度。 (二进制13 = 1101;长度为4)

然后 shift 2 by(4-2) // 4是二进制

中给定数字的长度

下面的java代码将为BigIntegers解决这个问题(基本上对所有数字都是如此)。

    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));        

    String num = br.readLine();
    BigInteger in = new BigInteger(num);
    String temp = in.toString(2);

    System.out.println(new BigInteger("2").shiftLeft(temp.length() - 2));

答案 13 :(得分:0)

p=2;
while(p<=n)
{
    p=2*p;
}
p=p/2;

答案 14 :(得分:0)

我在上面看到了另一个BigInteger解决方案,但实际上这很慢。如果我们要超越整数和更长的话,更有效的方法是

bigNumber^n

其中BigInteger nvalue = TWO.pow(BigIntegerMath.log2(value, RoundingMode.FLOOR)); 只是TWO

BigInteger.valueOf(2L)取自番石榴。

答案 15 :(得分:0)

我认为这是最简单的方法。

Integer.highestOneBit(n-1);

答案 16 :(得分:0)

简单的位操作应该可以工作

 public long largestPowerOf2 (long n)
 {      
 //check already power of two? if yes simply left shift
    if((num &(num-1))==0){
        return num>>1;
    }

  // assuming long can take 64 bits     
    for(int bits = 63; bits >= 0; bits--) {
        if((num & (1<<bits)) != 0){
            return (1<<bits);
        }
    }
    // unable to find any power of 2
    return 0;   
  }

答案 17 :(得分:0)

有点晚了但是......

(假设32位数。)

n|=(n>>1);
n|=(n>>2);
n|=(n>>4);
n|=(n>>8);
n|=(n>>16);
n=n^(n>>1);

说明:

第一个|确保设置原始顶部位和第二个最高位。第二个|确保这两个,以及接下来的两个,等等,直到你可能击中所有32位。即

100010101 - &gt; 111111111

然后我们删除除了顶部位之外的所有字符串,然后用1的字符串将1的字符串向左移动,最后只有一个顶部位,然后是0。

答案 18 :(得分:0)

/**
 * Find the number of bits for a given number. Let it be 'k'.
 * So the answer will be 2^k.
 */
public class Problem010 {

  public static void highestPowerOf2(int n) {
    System.out.print("The highest power of 2 less than or equal to " + n + " is ");
    int k = 0;
    while(n != 0) {
      n = n / 2;
      k++;
    }

    System.out.println(Math.pow(2, k - 1) + "\n");
  }

  public static void main(String[] args) {
    highestPowerOf2(10);
    highestPowerOf2(19);
    highestPowerOf2(32);
  }

}

答案 19 :(得分:0)

{{1}}