检查一个整数是否是另一个整数幂

时间:2010-12-13 12:59:42

标签: algorithm math

这是interview question:“给定2个整数x和y,检查x是否为y的整数幂”(例如,对于x = 8且y = 2,答案为“true”,对于x = 10且y = 2“假”)。

显而易见的解决方案是:

int n = y; while(n < x) n *= y; return n == x

现在我正在考虑如何改进它。

当然,我可以检查一些特殊情况:例如xy都应为奇数或偶数,即我们可以检查xy的最低有效位。但是我想知道我是否可以改进核心算法本身。

13 个答案:

答案 0 :(得分:26)

你最好重复将y分成x。第一次得到非零余数时,你知道x不是y的整数幂。

while (x%y == 0)  x = x / y
return x == 1

这将处理第一次迭代时的奇数/偶数点。

答案 1 :(得分:21)

表示 log y (x)应为整数。不需要任何循环。在 O(1)时间

public class PowerTest {

    public static boolean isPower(int x, int y) {
        double d = Math.log(Math.abs(x)) / Math.log(Math.abs(y));

        if ((x > 0 && y > 0) || (x < 0 && y < 0)) {
            if (d == (int) d) {
                return true;
            } else {
                return false;
            }
        } else if (x > 0 && y < 0) {
            if ((int) d % 2 == 0) {
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
    }

    /**
     * @param args
     */
    public static void main(String[] args) {

        System.out.println(isPower(-32, -2));
        System.out.println(isPower(2, 8));
        System.out.println(isPower(8, 12));
        System.out.println(isPower(9, 9));
        System.out.println(isPower(-16, 2));
        System.out.println(isPower(-8, -2));
        System.out.println(isPower(16, -2));
        System.out.println(isPower(8, -2));
    }

}

答案 2 :(得分:7)

这将以O(log N)步骤查找指数:

#define MAX_POWERS 100

int is_power(unsigned long x, unsigned long y) {
  int i;
  unsigned long powers[MAX_POWERS];
  unsigned long last;
  last = powers[0] = y;

  for (i = 1; last < x; i++) {
    last *= last; // note that last * last can overflow here!
    powers[i] = last;
  }
  while (x >= y) {
    unsigned long top = powers[--i];
    if (x >= top) {
      unsigned long x1 = x / top;
      if (x1 * top != x) return 0;
      x = x1;
    }
  }
  return (x == 1);
}

此代码不处理负数,但在i = 1

时可以使用某些条件代码轻松完成

答案 3 :(得分:4)

    double a=8;
    double b=64;

    double n = Math.log(b)/Math.log(a);
    double e = Math.ceil(n);

    if((n/e) == 1){
        System.out.println("true");
    } else{
       System.out.println("false");
    }

答案 4 :(得分:3)

对于正数,这看起来非常快,因为它找到所需功率的下限和上限,然后应用二进制搜索。

#include <iostream>
#include <cmath>
using namespace std;

//x is the dividend, y the divisor.
bool isIntegerPower(int x, int y)
{
    int low = 0, high;
    int exp = 1;
    int val = y;
    //Loop by changing exponent in the powers of 2 and
    //Find out low and high exponents between which the required exponent lies.
    while(1)
    {
        val = pow((double)y, exp);
        if(val == x)
            return true;
        else if(val > x)
            break;
        low = exp;
        exp = exp * 2;
        high = exp;
    }
    //Use binary search to find out the actual integer exponent if exists
    //Otherwise, return false as no integer power.
    int mid = (low + high)/2;
    while(low < high)
    {
        val = pow((double)y, mid);
        if(val > x)
        {
            high = mid-1;
        }
        else if(val == x)
        {
            return true;
        }
        else if(val < x)
        {
            low = mid+1;
        }
        mid = (low + high)/2;
    }
    return false;
}

int main()
{
    cout<<isIntegerPower(1024,2);
}

答案 5 :(得分:2)

我会像这样实现这个功能:

bool IsWholeNumberPower(int x, int y)
{
    double power = log(x)/log(y);
    return floor(power) == power;
}

这不应该像在浮点比较中那样在delta中检查,因为我们正在检查整数。

答案 6 :(得分:2)

再想一想,不要这样做。它不适用于否定x和/或y请注意,现在提供的所有其他基于log的答案也会以完全相同的方式中断。

以下是快速通用解决方案(使用Java):

static boolean isPow(int x, int y) {
    int logyx = (int)(Math.log(x) / Math.log(y));
    return pow(y, logyx) == x || pow(y, logyx + 1) == x;
}

其中pow()是整数取幂函数,如Java中的以下内容:

static int pow(int a, int b) {
    return (int)Math.pow(a, b);
}

(这是由于Math.pow提供的以下保证:“如果两个参数都是整数,那么结果完全等于将第一个参数提升到第二个参数的幂的数学结果。 。“)

使用对数而不是重复除法的原因是性能:log is slower than division时,它会慢一个小的固定倍数。同时它确实消除了对循环的需要,因此为您提供了一个恒定时间算法。

答案 7 :(得分:2)

y为2的情况下,有一种快速方法可以避免需要循环。这种方法可以扩展到y具有2的更大幂的情况。

如果x是2的幂,则x的二进制表示只有一个设置位。有一个相当简单的bit-fiddling算法,用于在O(log n)时间内对整数中的位进行计数,其中n是整数的位宽。许多处理器也有专门的指令,可以将其作为单个操作处理,大约与(例如)整数否定一样快。

然而,为了扩展该方法,首先采用略微不同的方法来检查单个位。首先确定最低有效位的位置。同样,有一个简单的比特摆弄算法,许多处理器都有快速的专用指令。

如果该位是唯一位,则为(1 << pos) == x。这里的优点是,如果你测试的是4的幂,你可以测试pos % 2 == 0(单个位在偶数位置)。测试任何2的幂,你可以测试pos % (y >> 1) == 0

原则上,你可以做类似的事情来测试3的幂和3的幂。问题是你需要一个在3号基础上工作的机器,这有点不太可能。您当然可以测试任何值x,看看它在基础y中的表示是否只有一个非零数字,但您要做的工作更多,而您已经在做了。以上内容利用了计算机以二进制方式工作的事实。

可能不值得在现实世界中做。

答案 8 :(得分:2)

这是一个Python版本,汇集了@salva和@Axn的想法,并被修改为不生成任何大于给定数字的数字,并且仅使用简单存储(读取,&#34;无列表&#34;)反复削减兴趣的数量:

def perfect_base(b, n):
    """Returns True if integer n can be expressed as b**e where
    n is a positive integer, else False."""

    assert b > 1 and n >= b and int(n) == n and int(b) == b

    # parity check
    if not b % 2:
        if n % 2:
            return False  # b,n is even,odd
        if b == 2:
            return n & (n - 1) == 0
        if not b & (b - 1) and n & (n - 1):
            return False  # b == 2**m but n != 2**M
    elif not n % 2:
        return False  # b,n is odd,even

    while n >= b:
        d = b
        while d <= n:
            n, r = divmod(n, d)
            if r:
                return False
            d *= d
    return n == 1

答案 9 :(得分:1)

以前的答案都是正确的,我喜欢Paul的最佳答案。它简单而干净。 以下是他建议的Java实现:

public static boolean isPowerOfaNumber(int baseOrg, int powerOrg) {
    double base = baseOrg;
    double power = powerOrg;

    while (base % power == 0)
        base = base / power;
    // return true if base is equal 1
    return base == 1;
}

答案 10 :(得分:1)

如果数字太大,请使用日志功能以减少时间复杂度:

import math
base = int(input("Enter the base number: "))
for i in range(base,int(input("Enter the end of range: "))+1):
    if(math.log(i) / math.log(base) % 1 == 0 ):
        print(i)

答案 11 :(得分:0)

如果您可以访问y的最大功率,可以在所需的数据类型中使用,这是解决此问题的一种非常灵活的方法。

让我们说,y == 3。因此,我们需要检查x是否为3的幂。

鉴于我们需要检查整数x是否为3的幂,让我们从已经掌握的信息开始考虑这个问题。

1162261467是3中最大的幂,可以放入Java int。
1162261467 = 3^19 + 0

给定的x可以表示为[(a power of 3) + (some n)]。我认为能够证明如果n为0(发生 iff x是3的幂),1162261467 % x = 0就足够了。

因此,要检查给定的整数x是否为3的幂,请检查x > 0 && 1162261467 % x == 0是否。

泛化。要检查给定的整数x是否是给定整数y的幂,请检查x > 0 && Y % x == 0Y是否是y的最大幂整数数据类型。

一般的想法是,如果A具有Y的某种能力,则A可以表示为B/Ya,其中a是某个整数且A < B。它遵循A > B完全相同的原则。 A = B案例是基本的。

答案 12 :(得分:0)

我找到了这个解决方案 //检查如果A可以表示为两个整数的幂

    int isPower(int A)
    {
     int i,a;
     double p;
     if(A==1)
     return 1;
     for(int a=1; a<=sqrt(A);++a )
     {
         p=log(A)/log(a);
         if(p-int(p)<0.000000001)
         return 1;
     }
    return 0;
   }

binarycoder.org