【问题标题】:Computing the power function in O(1)在 O(1) 中计算幂函数
【发布时间】:2018-09-29 10:40:48
【问题描述】:

我写了一个函数来计算 O(logb) 中的 pow(a,b)。

double pow(double a, int b){
  double res=1;
    while(b>0){
        if (b%2==1){
            res=res*a;
        }
      b=b>>1;
      a=a*a;

    }
    return res;
}

我偶然发现了一个问题,是否可以在O(1) 时间编写函数 pow(double a, double b)。然而我还没有找到答案。

【问题讨论】:

  • 如果可能的话,您不认为标准实现会使用这种方法吗?
  • 假设 IEEE754,我们有 64 位的双精度,即。 e. 2^64 个值,两个参数,2^65 种组合。由于我们有一组有限的输入,我们总是是 O(1)...
  • 要说明计算复杂性的意义,您需要定义您计算的基本操作是什么,以及根据什么变量。
  • 正如 Aconcagua 所指出的,您有一组有限的输入。所以你可以使用一个(相当大的!)查找表。
  • 您必须在double bint b之间进行选择;这些是不同的问题。

标签: c++ algorithm math


【解决方案1】:

如果您不允许自己使用标准 pow/exp/log 函数或预计算表,但允许浮点乘法,那么您的解决方案是最佳的(恒定时间是不可能的)。

【讨论】:

    【解决方案2】:

    如果您允许对参数(a 正数、ab 双精度数)和结果(双精度数)进行一些限制,您可以使用

    exp(b * log(a))
    

    这通常并不准确,即使可以得出准确的结果。在我的 Borland Delphi 时代,我编写了一个类似的例程,但使用基数 2 而不是经常使用的基数 e。这提高了代码的准确性和速度,因为 CPU 以2 为基础工作。但我不知道如何在 C++ 中做到这一点。

    【讨论】:

    • 虽然不是 O(1)... 是吗?
    • @Ash:由于ab 是双精度的,所以explog 函数(大部分)由CPU 处理并使用有限数量的CPU 周期,因此是第一个。您的代码的优点是它更经常返回准确的答案。
    • @Ash:我应该补充一点,您的代码还允许 a 为零或负数。
    • 我不是 OP ;) 但我对你的解释持怀疑态度......你能否添加一些参考资料?也许我们可以接近O(1),但从理论上讲,我认为上限是对数......
    • @Ash:你说得对,对于 任意精度,log 函数不是 O(1)……但这就是为什么我强调你的参数是 双打。 (我刚刚将其添加到我的主要答案中,从我之前的评论中复制。)对于有限的位数,log 和 exp 近似运算变为 O(1)。
    【解决方案3】:

    是的,您可以使用预计算编写一个。将所有可能的功率计算到一个表格中,并在必要时循环起来。这种方法确实适用于很多问题。

    现在,假设您找到了一个除了查表之外的新算法,并且新算法的复杂度为 O(1)。现在是结果;

    • 加法的复杂度是 O(1) x^b * x^c = x^(a+c)。计算并取对数以 b 为底,尤其是在以 2 为底的情况下。

    因此,您可以使用新算法减少几乎所有算术运算。

    正如 Yvies 所说,这是最佳选择。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-09-27
      • 1970-01-01
      • 1970-01-01
      • 2022-11-18
      • 2014-11-26
      • 1970-01-01
      • 1970-01-01
      • 2015-07-22
      相关资源
      最近更新 更多