【问题标题】:Best way to do powerOf(int x, int n)?做powerOf(int x,int n)的最佳方法?
【发布时间】:2010-03-30 02:29:15
【问题描述】:

所以给定 x 和幂 n,求解 X^n。 有一个简单的方法是O(n)... 我可以通过这样做将其归结为O(n/2)

numSquares = n/2;
numOnes = n%2;
return (numSquares * x * x + numOnes * x);

现在有一个O(log(n)) 解决方案,有人知道怎么做吗?它可以递归完成。

【问题讨论】:

  • 不需要递归完成;可以通过简单的迭代来完成。
  • 你知道 O(n/2) 和 O(n) 是一样的吗?

标签: c++ algorithm math big-o


【解决方案1】:

嗯,你知道 xa+b = xa xb 所以...

int pow(int x, unsigned int y)
{
  if (y == 0) return 1;
  if (y == 1) return x;
  int a = y / 2;
  int xa = pow(x, a);
  if (a + a == y) // y even
    return xa * xa;
  else
    return xa * xa * x;
}

【讨论】:

  • 您还需要if (y<0) { return (x==1)?1:0; } 并为y<0, x==0 抛出异常
  • 递归计算已经如此昂贵的东西,比如计算一个数字的幂似乎有点矫枉过正
  • 递归到底有什么过火之处?此外,它的计算成本不高,运行时间为 O(lg(n))。
  • 我应该说计算密集型,对此感到抱歉。该函数不是尾调用可优化的,我怀疑这里的函数调用开销与每次调用的执行时间相当。
  • 如果他想进行微优化,那么这取决于他。我正在展示一些优雅的东西来展示这个概念。递归解决方案几乎总是比迭代解决方案更容易理解。
【解决方案2】:

可以利用的数学概念是x<sup>2n+1</sup> = x<sup>2n</sup> ⋅ xx<sup>2n</sup> = x<sup>n</sup> ⋅ x<sup>n</sup>

【讨论】:

    【解决方案3】:

    通常的实现是这样的(摘自wikipedia article):

    long power(long x, unsigned long n)
    {
        long result = 1;
        while (n > 0) {
            /* n is odd, bitwise test */ 
            if (n & 1) {
                result *= x;
            }
            x *= x;
            n /= 2;     /* integer division, rounds down */
        }
        return result;
    }
    

    递归不是必需的或(我会说)特别可取,尽管它可以赢得显而易见:

    long power(long x, unsigned long n)
    {
        if (n == 0) return 1;
        long result = power(x, n/2); // x ^ (n/2)
        result *= result;            // x ^ (n/2)*2
        if (n & 1) result *= x;      // x ^ n
        return result;
    }
    

    当然,在任何版本中,您都会很快溢出 long。您可以将相同的算法应用于您最喜欢的 bigint 表示,尽管任何 bigint 库都将包含整数幂函数。

    上述函数的两个版本都为 power(0,0) 返回 1。您可能会也可能不会认为这是一个错误。

    【讨论】:

    • 有趣的事实:g77 通过平方使用取幂来计算积分幂。
    【解决方案4】:

    您可以在此处找到解释:Fast exponentiation。对于 n 的某些值,您可以使用比使用二的幂技巧更少的乘法来计算 x^n。

    【讨论】:

      【解决方案5】:

      标准技巧是按顺序生成 x 的幂 x2、x4、x8、x16 , x32, ... 并包括结果中需要的那些。

      【讨论】:

      • 除非我没有得到你的答案,否则你不能无限地这样做,对吧?
      • @Mike:如果你有一台无限的计算机,你只能无限地做任何事情,而我们大多数人都被普通的、非常有限的计算机所困。如果你使用多精度算术包,你可以处理足够大的数字,它们会让你大吃一惊。
      • Mike:为什么要无限做?你只需要做到n
      • @gabe 是真的。尽管如此,我认为 Poita_ 提供了最好的答案。
      • +1:这里有一个例子来说明这个答案。假设我们必须计算 x^26。现在,26 = 11010 二进制。 “1”位置表示 16、8 和 2。因此,x^26 = (x^16) * (x^8) * (x^2)。现在,如果计算了系列 x、x^2、x^4、x^8、x^16,那么我们可以选择系列中的选定项目并将它们多个。总结:要计算 x^n,将 n 转换为二进制,找到为 1 的位位置(总是 2 的幂),从低位开始计算,然后乘以合适的位。
      猜你喜欢
      • 2017-06-13
      • 1970-01-01
      • 1970-01-01
      • 2022-01-09
      • 2012-12-14
      • 1970-01-01
      • 2013-05-29
      • 1970-01-01
      • 2011-06-25
      相关资源
      最近更新 更多