|
返回主页<- |
| 高精度求乘幂 |
|
先从简单一些的整数乘幂开始,
因为实数乘幂的计算可归结为正整数次方,
开正整数次方和求倒数.
见 指数&对数
|
| 指数是整数的情况 |
| 先看一个例子:
计算 216 .我们可以通过代数式的变形来减少计算步骤:
216
= 48 = 164 = 2562 = 65536
类似地计算 220.
220
= 410 = 165 = 164*16 = 2562*16
= 65536*16 = 1048576
可见,
我们把问题转化为多次求两大数的积.
如果求积时仍用经典乘法, 并不能使计算时间显著减少,
因为时间复杂度仍是O(n2). 由于我们有快速乘法,
使得这么做可以使乘幂计算快许多:
////求
xy ////
result=x;
While
y mod 2=0
{
y=y
div 2;
result=result*result;
}
tmp=1;
While
y<>1
{
If
y mod 2<>0 then { tmp=tmp*result; y=y-1;};
While
y mod 2=0
{
y=y
div 2;
result=result*result;
}
}
result=result*tmp
result就是所求结果.
对以上代码进行优化:
////求
xy ////
tmp=x;
result=1;
While
y<>1
{
While
(y and 1)<>1
{
y=y
shr 1;
tmp=tmp*tmp;
}
result=result*tmp;
y=y-1;
}
result=tmp*result;
还有一种基于二进制的乘方算法,
例:
a15=a2^3+2^2+2+1=(((a2)·a)2·a)2·a
由以上,设
e=(en-1,en-2,...,e1,e0)
为指数的二进制表示;
1.
p←ae(n-1); i←n-2;
2.
p=p2;
3.
若 ei=1,p=pa;
4.
i--; 若 i>=0 转到2;
5.
输出 p.
|
| 实数乘幂的计算 |
|
正如开头所说的"可归结为正整数次方,
开正整数次方和求倒数". 但是对于类似
14^(100000000π)
的大实数乘幂就无能为力了.
关于这个问题站长也没什么好办法.只好按下列步骤处理
x^y:
将指数y分为整数a,
小数部分b .
由
x^y=x^(a+b)=x^a*x^b
按整数指数乘幂计算
x^a.
利用
x^b=e^(b*ln(x)) 计算第二部分.
两部分相乘得
x^y.
其中计算又要涉及到乘幂 e^() 的计算,
似乎又回到开头的问题.
不过, 幸好有
ey=1+y+y2/2!+y3/3!+...+yn/n!+...
同样可把把 y 分为整数,小数部分,整数部分同样是按整数指数乘幂计算(
e 的值预先用 e^1
求出),
小数部分按上式算.
|
|
ex=1+x+x2/2!+x3/3!+...+xn/n!+...
|
|
|
直接计算(一项一项地算)的时间复杂度容易求得是O(n2),
但这已经几乎是计算它的最好的式子了.
算之前可以利用
ex=(ex/2)2
递归地把指数化到适当小. 再代入幂级数.
|
|
没有经过实践的:
|
|
|
对于 e1/x=1+1/x+1/(x22!)+1/(x33!)+...+1/(xnn!)+...
设:
Q(a,b)=(a+1)(a+2)...(b-1)bxb-a
P(a,b)=Q(a+1,b)+Q(a+2,b)+...Q(b-1,b)+1
则:
|
|
|
n |
|
|
|
|
e1/x |
= |
∑ |
1 |
=1+ |
P(0,n) |
|
|
| k!xk |
Q(0,n) |
|
|
k=0 |
|
|
|
有初值
P(c,c+1)=1,
Q(c,c+1)=(c+1)x,
P(c,c+2)=(c+2)x+1,
Q(c,c+2)=(c+1)(c+2)x2 .
|
递推关系 |
m= |
[(a+b)/2]
也可以取任意 0<k<1
计算 m=[k(a+b)] |
|
P(a,b)= |
P(a,m)Q(m,b)+P(m,b) |
|
Q(a,b)= |
Q(a,m)Q(m,b) |
|
Last update 10/2/2004
|