我需要找到比给定数字少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
如何解决这个问题?
答案 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}}