c ++中整数的幂

时间:2009-10-01 18:34:22

标签: c++ mingw

我需要从pow(a,b)得到一个整数的结果(a和b都是整数)。目前包含(int) pow( (double)a, (double)b)的计算是错误的。也许有人可以帮助一个用整数做pow(a,b)的函数并返回一个整数?

但是这里有一个奇怪的部分:我使用Geany(和g ++ / gcc编译器)在Linux中创建了我的脚本,只编译了pow(a,b)脚本并且工作正常。但在大学里我有Dev-C ++(和MS Windows)。在Dev-C ++中,脚本没有使用[Warning] converting to

中的错误double' int'进行编译

我需要在Windows(和Mingw编译器)下使这个scrpit工作。

11 个答案:

答案 0 :(得分:54)

比Zed更好的递归方法。

int myPow(int x, int p)
{
  if (p == 0) return 1;
  if (p == 1) return x;

  int tmp = myPow(x, p/2);
  if (p%2 == 0) return tmp * tmp;
  else return x * tmp * tmp;
}

更好的复杂性有O(log²(p))而不是O(p)。

答案 1 :(得分:17)

或者你可以使用一点点的模板元编程:)

template<int X, int P>
struct Pow
{
    enum { result = X*Pow<X,P-1>::result };
};
template<int X>
struct Pow<X,0>
{
    enum { result = 1 };
};
template<int X>
struct Pow<X,1>
{
    enum { result = X };
};

int main()
{
    std::cout << "pow(3,7) is " << Pow<3,7>::result << std::endl;
    return 0;   
}

此代码具有最佳复杂性 O(1),因为评估将在编译时进行。当然,这只适用于整数值。 但是,此功能仅用于完整性(和乐趣)。

答案 2 :(得分:13)

主要是回复Zeds的简单递归......

为什么递归假定比迭代更好?特别是在C ++中。怎么了......

int myPow (int x, int p) {
  int i = 1;
  for (int j = 1; j <= p; j++)  i *= x;
  return i;
}

我并不是说你的回答是错误的,或者更糟糕的是 - 只是因为我认为它很好因为它是递归的。 IMO,特别是在C ++中,这种偏见会导致程序缓慢甚至破坏。缓慢的程序,因为你正在增长一个巨大的堆栈,导致缓存和虚拟内存分页。程序损坏,因为你得到一个堆栈溢出,迭代解决方案可以工作。

有些人会看你的答案并认为它是尾递归的,并且无论如何都会被优化为迭代。当然这不是真的 - 在每次递归调用退出之后,还有一个繁殖仍然要做,因此它不是尾递归。问题是,在C ++中,有许多更微妙的东西阻止了尾递归优化 - 即使编译器完全执行它们。例如......

void myrecurse (plan *p)
{
  plan i;
  i.prev = p;
  //  more plan setup, checks, and special case handling

  myrecurse (&i);
}

在这种情况下,所有“计划”实例都必须保留在堆栈中。因此,不能丢弃堆栈帧。因此,即使在递归调用之后完成零操作,这也不能在迭代中进行优化。甚至没有像析构函数清理这样的隐藏操作,因为计划被假定为POD结构。

顺便提一下,这是基于我在实际代码中所做的事情 - 在递归期间计划的数据结构操作,但在递归到达根/叶子之前,原始节点中没有任何改变,需要所有新节点已经成功分配,获得了所有锁,并且没有任何限制可以使情况变得更糟。此时,通过该链接的计划实例列表进行迭代以提交更改 - 逻辑作为迭代更清晰,而不是分解为与递归调用的展开相关的片段。

这里的要点显然不是声称递归是自动坏的。当人们似乎假设递归比默认迭代更好时,这只会让我感到紧张。

答案 3 :(得分:3)

我假设你的家庭作业是写一个积分指数函数。首先,看看指数是什么:

http://en.wikipedia.org/wiki/Exponent

然后,在教科书中查看如何在C中乘以数字。您将要使用for循环。

答案 4 :(得分:3)

尾递归函数不是最好的吗?类似的东西:

int myPow_helper(int x, int p, int result) {
   if (p == 0) {
      return result;
   } else {
      return myPow_helper(x, p-1, result*x);
   }
}

int myPow(int x, int p) {
   return myPow_helper(x, p, 1);
}

答案 5 :(得分:2)

不要将double转换为(int) pow((double)a, (double)b)行中的int,而是尝试舍入pow的结果,然后在必要时转换为int。

当你截断时,这可能是浮点问题之一,特别是当你的结果被一个人关闭时。

答案 6 :(得分:2)

Binary powering,又名exponentiation by squaring

int powi (int base, unsigned int exp)
{
    int res = 1;
    while (exp) {
        if (exp & 1)
            res *= base;
        exp >>= 1;
        base *= base;
    }
    return res;
}

请注意,这为powi(0,0)返回1。

答案 7 :(得分:1)

C ++标准没有int pow(int, int)(它有double pow(double, int)float ...)。微软的cmath使用的是没有ip的C math.h。某些cmath标头定义了pow的模板版本。

$ cat main.cpp
#include <cmath>

int main() {
  std::pow(2,2);
}

$ gcc main.cpp # this cmath has template pow
...snip... std::pow<int, int>(int, int)]+0x16): undefined reference to `pow'
collect2: ld returned 1 exit status
1 ;( user@host:
$ gcc main.cpp -lm

在Google Code上搜索function:ipow lang:c++

以下是第一个链接的示例:

template <typename Type1, typename Type2>
Type1 ipow(Type1 a, Type2 ex)
// Return a**ex
{
    if ( 0==ex )  return 1;
    else
    {
        Type1 z = a;
        Type1 y = 1;
        while ( 1 )
        {
            if ( ex & 1 )  y *= z;
            ex /= 2;
            if ( 0==ex )  break;
            z *= z;
        }
        return y;
    }
}

请参阅calculating integer powers (squares, cubes, etc.) in C++ code

答案 8 :(得分:0)

一个很好的递归方法,你可以炫耀:

int myPow(int x, int p) {
  if (p == 0) return 1;
  if (p == 1) return x;
  return x * myPow(x, p-1);
}

答案 9 :(得分:0)

为何线性? 试试对数!!

long long powx( int val, int exp )
{
    long long actual = val;
    long long prod = 1;
    int i;

    for ( i = 0; i < 32; i++ )
    { 
        if ( exp & 0x1 )
        {
            prod *= actual;
        }

        exp >>= 1;

        actual *= actual;
    }

    return prod;
}

答案 10 :(得分:0)

这里有两种选择,当我们想要计算功率(a,n)时,我们可以编写非常短且在O(logn)时间内工作的代码,但是是递归的,因此需要为每个调用创建新的堆栈帧,需要比循环迭代更多的时间。所以简短的代码是:

int power(int a, int n){
    if(n == 0) return 1;
    int keep = power(a,n/2);
    if(n & 1) return keep*keep*a;   // (n & 1) is and operation of 1 and the 
    return keep*keep;               // last bit of n
}

至于更快的代码,这里是使用while循环:

int power(int a, int n) {
    int res = 1;
    while (n) {
        if (n & 1)
            res *= a;
        a *= a;
        n >>= 1;
    }
    return res;
}