我有一个定点bignumber库,想要实现快速阶乘,没有精度损失.
在纸上做了一些数学技巧后,我得到了这个公式:
(4N)!=((2N)!).((2N)!).{ (2N+1).(2N+3).(2N+5)...(4N-1) }.(2^N)/(N!)
Run Code Online (Sandbox Code Playgroud)
这已经非常快了,并且通过一些编程技巧,复杂性接近~ O(log(n))
.
要清楚,我目前的实现是:
//---------------------------------------------------------------------------
longnum fact(const DWORD &x,longnum &h) // h return (x>>1)! to speed up computation
{
if (x==0) { h=1; return 1; }
if (x==1) { h=1; return 1; }
if (x==2) { h=1; return 2; }
if (x==3) { h=1; return 6; }
if (x==4) { h=2; return 24; }
int N4,N2,N,i; longnum c,q;
N=(x>>2);
N2=N<<1;
N4=N<<2;
h=fact(N2,q); // get 2N! and N!
c=h*h; for (i=(N2+1)|1;i<=N4;i+=2) c*=i; c/=q; // c= …
Run Code Online (Sandbox Code Playgroud) 在"像程序员一样思考"一书中,下面的递归函数被称为"非常低效",我无法弄清楚为什么(这本书没有解释).似乎没有任何不必要的计算.是因为调用这么多函数(多次使用相同的函数)的开销,从而为每次调用函数设置环境?
int factorial(int n) {
if (n == 1) return 1;
else return n * factorial(n-1);
}
Run Code Online (Sandbox Code Playgroud) def fact(n):
fac = 1
while (n>1):
fac = fac*n
n -= 1
return fac
z = 0
t = int(raw_input())
nz = []
for i in range(0,t):
c = 0
n = int(raw_input())
z = fact(n)
z = list(str(z))
for j in range(len(z)-1,1,-1):
if z[j] != '0':
break
else:
c +=1
nz[i].append(c)
for k in range(0,t):
print nz[k]
Run Code Online (Sandbox Code Playgroud)
你好,我得到了
Indexerror:索引超出范围"nz [i] .append(c)
这个程序应该计算N的阶乘中的尾随零.你能帮我优化我的代码,所以它也可以运行N的大值吗?