我正在尝试确定使用指数的算法的渐近运行时间,但我不确定如何以编程方式计算指数。
我特意寻找用于双精度浮点数的pow()算法。
答案 0 :(得分:13)
我有机会看看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**
计算。其中任何一个都没有循环。因此,尽管浮点基元的复杂性,它看起来像渐近恒定时间算法。
欢迎浮点专家(我不是其中一位)发表评论。 : - )
答案 1 :(得分:2)
除非他们发现了更好的方法,否则我认为三角函数,对数函数和指数函数(例如指数增长和衰减)的近似值通常使用算术规则和泰勒级数< / strong>扩展以产生精确到请求精度范围内的近似结果。 (有关幂级数,泰勒级数和Maclaurin级数函数扩展的详细信息,请参阅任何微积分书。)请注意,自从我做了这些以来已经有一段时间了,所以我无法告诉你,例如,究竟如何计算您需要包含的系列中的术语数量可以保证在双精度计算中小到可以忽略不计的误差。
例如,针对e ^ x的Taylor / Maclaurin级数展开是:
+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个术语之后就停止了,那么你产生的近似结果与实际的结果不同^ x函数值乘以一个相当容易计算的余数。
对于指数的好消息是,它很好地收敛,并且其多项式展开的项相当容易迭代编码,所以你可能(重复, MIGHT - 记住,它已经有一段时间了甚至不需要预先计算你需要多少个术语来保证你的误差低于精度,因为你可以在每次迭代时测试贡献的大小,并在它变得足够接近零时停止。在实践中,我不知道这种策略是否可行 - 我必须尝试一下。我早就忘记了重要的细节。如:机器精度,机器误差和舍入误差等等。
另外,请注意,如果您没有使用e ^ x,但是您正在使用其他基数(如2 ^ x或10 ^ x)进行增长/衰减,则近似多项式函数会发生变化。
答案 2 :(得分:1)
对于整数指数,通常的方法是将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
答案 3 :(得分:0)
如果我正在编写针对Intel的pow功能,我会返回exp2(log2(x)* y)。即使我记得第一年的微积分和研究生数值分析,英特尔的log2微码肯定比我能编码的任何东西都要快。
答案 4 :(得分:0)
您可以使用exp(n * ln(x))来计算x n 。 x和n都可以是双精度浮点数。自然对数和指数函数可以使用泰勒级数计算。在这里你可以找到公式:http://en.wikipedia.org/wiki/Taylor_series