代码之家  ›  专栏  ›  技术社区  ›  Ryan Fox

如何计算指数?

  •  7
  • Ryan Fox  · 技术社区  · 17 年前

    我正在尝试确定我的一个算法的渐进运行时,它使用指数,但我不确定指数是如何以编程方式计算的。

    我专门寻找用于双精度浮点数的pow()算法。

    5 回复  |  直到 17 年前
        1
  •  13
  •   C. K. Young    17 年前

    我有机会研究fdlibm的实现。注释描述了使用的算法:

     *                    n
     * Method:  Let x =  2   * (1+f)
     *      1. Compute and return log2(x) in two pieces:
     *              log2(x) = w1 + w2,
     *         where w1 has 53-24 = 29 bit trailing zeros.
     *      2. Perform y*log2(x) = n+y' by simulating muti-precision
     *         arithmetic, where |y'|<=0.5.
     *      3. Return x**y = 2**n*exp(y'*log2)
    

    然后列出所有处理的特殊情况(0、1、inf、nan)。

    在所有特殊情况处理之后,代码中最密集的部分涉及 log2 2** 计算。其中任何一个都没有回路。因此,尽管浮点原语很复杂,但它看起来像一个渐进的常量时间算法。

    欢迎浮点专家(我不是其中之一)发表评论。-)

        2
  •  2
  •   gsarnold    17 年前

    除非他们发现了更好的方法,否则我相信三角函数、对数函数和指数函数(例如指数增长和衰减)的近似值通常是用算术规则和 泰勒级数 扩展以产生精确到所需精度范围内的近似结果。(有关幂级数、泰勒级数和麦克劳林级数展开式的详细信息,请参阅任何微积分书。)请注意,我已经有一段时间没有做过这些了,所以我不能告诉您,例如,如何精确地计算级数中的项数,您需要包括保证一个足够小的误差,在一个D中可以忽略不计。双精度计算。

    例如,e^x的泰勒/麦克劳林级数展开式是:

          +inf [ x^k ]           x^2    x^3      x^4        x^5
    e^x = SUM  [ --- ] = 1 + x + --- + ----- + ------- + --------- + ....
          k=0  [  k! ]           2*1   3*2*1   4*3*2*1   5*4*3*2*1
    

    如果你把所有的项(k从0到无穷大),这个展开式是精确和完整的(没有错误)。

    然而,如果你不把所有的项都取到无穷大,但是你在说5个项或50个项或其他什么之后就停止了,你就产生了一个 近似 与实际e^x函数值不同的结果是一个很容易计算的余数。

    指数的好消息是它很好地收敛,并且它的多项式展开项很容易迭代编码,所以 可以 (重复, 可能 -记住,这已经有一段时间了)甚至不需要预先计算出需要多少项来保证误差小于精度,因为您可以在每次迭代中测试贡献的大小,并在接近零时停止。在实践中,我不知道这个策略是否可行——我必须尝试一下。我早就忘记了一些重要的细节。如:机器精度、机器误差、舍入误差等。

    另外,请注意,如果您不使用e^x,但使用其他基数(如2^x或10^x)进行增长/衰减,则近似多项式函数会发生变化。

        3
  •  1
  •   Andru Luvisi    17 年前

    对于整数指数,将a提高到b的通常方法如下:

    result = 1
    while b > 0
      if b is odd
        result *= a
        b -= 1
      b /= 2
      a = a * a
    

    它通常是指数大小的对数。该算法基于不变的“a^b*result=a0^b0”,其中a0和b0是a和b的初始值。

    对于负指数或非整数指数,需要对数、近似和数值分析。运行时间将取决于所使用的算法以及库调整的精度。

    编辑:由于似乎有一些兴趣,这里有一个没有额外乘法的版本。

    result = 1
    while b > 0
      while b is even
        a = a * a
        b = b / 2
      result = result * a
      b = b - 1
    
        4
  •  0
  •   Windows programmer    17 年前

    如果我写一个针对Intel的POW函数,我将返回exp2(log2(x)*y)。英特尔为log2开发的微码肯定比我能编写的任何代码都要快,即使我还记得我第一年的微积分和研究生的数值分析。

        5
  •  0
  •   akalenuk    17 年前

    可以使用exp(n*ln(x))计算x n . X和N都可以是双精度浮点数。自然对数和指数函数可用泰勒级数计算。您可以在这里找到公式: http://en.wikipedia.org/wiki/Taylor_series

    推荐文章