shshsh_0510 发表于 2008-4-17 08:38:27

呵呵,liangbch已经给出了:P

无心人 发表于 2008-4-17 08:51:56

:lol

由liangbch给出的网页得到的算法
只需要长整数乘以32位小整数和长加法算法计算到足够精度

然后进行一次长除法,再移位加一了

算法复杂度显然小于他自己写的程序

具体算法俺已从他给出网页整理到19#

liangbch 发表于 2008-4-17 10:39:46

回复 17楼 mathe.
求 x,使得 $ log10(x!)=n $有更有效的算法,只是这部分代码占用的时间很小,我在之前的代码中没有给出更有效更复杂的代码。

下面贴出代码:
函数 faclogEquation(double f) 返回 方程 $log10(x!)=f $ 的解#definePI 3.1415926535897932384626433832795   
#defineLOG10 2.3025850929940456840179914546844
#defineLOGS2PI 0.91893853320467274178032973640562   //log(sqrt(2*pi))
typedef unsigned long DWORD;

typedef struct _logfacpair
{
unsigned long n;
double logfac;
}LOGFAC_PAIR;

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>
/*
计算e,使用HugeCalc,一个简单的版本
*/
//#define DEBUG_LOG_FAC

const double logfac[]=
{
    0.000000,   // 0
    0.000000,   // 1
    0.693147,   // 2
    1.791759,   // 3
    3.178054,   // 4
    4.787492,   // 5
    6.579251,   // 6
    8.525161,   // 7
   10.604603,   // 8
   12.801827,   // 9
   15.104413,   // 10
   17.502308,   // 11
   19.987214,   // 12
   22.552164,   // 13
   25.191221,   // 14
   27.899271,   // 15
   30.671860,   // 16
   33.505073,   // 17
   36.395445,   // 18
   39.339884,   // 19
   42.335616,   // 20
   45.380139,   // 21
   48.471181,   // 22
   51.606676,   // 23
   54.784729,   // 24
   58.003605,   // 25
   61.261702,   // 26
   64.557539,   // 27
   67.889743,   // 28
   71.257039,   // 29
   74.658236,   // 30
   78.092224,   // 31
   81.557959,   // 32
   85.054467,   // 33
   88.580828,   // 34
   92.136176,   // 35
   95.719695,   // 36
   99.330612,   // 37
102.968199,   // 38
106.631760,   // 39
110.320640,   // 40
114.034212,   // 41
117.771881,   // 42
121.533082,   // 43
125.317271,   // 44
129.123934,   // 45
132.952575,   // 46
136.802723,   // 47
140.673924,   // 48
144.565744,   // 49
148.477767,   // 50
152.409593,   // 51
156.360836,   // 52
160.331128,   // 53
164.320112,   // 54
168.327445,   // 55
172.352797,   // 56
176.395848,   // 57
180.456291,   // 58
184.533829,   // 59
188.628173,   // 60
192.739047,   // 61
196.866182,   // 62
201.009316,   // 63
205.168199,   // 64
209.342587,   // 65
213.532241,   // 66
217.736934,   // 67
221.956442,   // 68
226.190548,   // 69
230.439044,   // 70
234.701723,   // 71
238.978390,   // 72
243.268849,   // 73
247.572914,   // 74
251.890402,   // 75
256.221136,   // 76
260.564941,   // 77
264.921650,   // 78
269.291098,   // 79
273.673124,   // 80
278.067573,   // 81
282.474293,   // 82
286.893133,   // 83
291.323950,   // 84
295.766601,   // 85
300.220949,   // 86
304.686857,   // 87
309.164194,   // 88
313.652830,   // 89
318.152640,   // 90
322.663499,   // 91
327.185288,   // 92
331.717887,   // 93
336.261182,   // 94
340.815059,   // 95
345.379407,   // 96
349.954118,   // 97
354.539086,   // 98
359.134205,   // 99
363.739376,   // 100
368.354496,   // 101
372.979469,   // 102
377.614198,   // 103
382.258589,   // 104
386.912549,   // 105
391.575988,   // 106
396.248817,   // 107
400.930948,   // 108
405.622296,   // 109
410.322777,   // 110
415.032307,   // 111
419.750806,   // 112
424.478193,   // 113
429.214392,   // 114
433.959324,   // 115
438.712914,   // 116
443.475088,   // 117
448.245773,   // 118
453.024896,   // 119
457.812388,   // 120
462.608179,   // 121
467.412200,   // 122
472.224384,   // 123
477.044665,   // 124
481.872979,   // 125
486.709261,   // 126
491.553448,   // 127
496.405478   // 128
};

const LOGFAC_PAIR logfac_tab[]=
{
{          1,   0.000000 },
{          2,   0.693147 },
{          4,   3.178054 },
{          8,   10.604603 },
{         16,   30.671860 },
{         32,   81.557959 },
{         64,   205.168199 },
{      128,   496.405478 },
{      256,   1167.256953 },
{      512,   2686.060309 },
{       1024,   6078.211803 },
{       2048,   13571.950932 },
{       4096,   29978.648040 },
{       8192,   65630.826536 },
{      16384,   142613.098657 },
{      32768,   307933.819731 },
{      65536,   661287.962119 },
{   131072,   1413421.993946 },
{   262144,   3008541.898276 },
{   524288,   6380485.734864 },
{    1048576,   13487781.810467 },
{    2097152,   28429191.113103 },
{    4194304,   59765644.367806 },
{    8388608,   125345820.522651 },
{   16777216,   262320712.469790 },
{   33554432,   547899575.985538 },
{   67108864,   1142315462.606553 },
{134217728,   2377663555.374189 },
{268435456,   4941392380.307250 },
{536870912,   10254915309.315521 },
{ 1073741824,   21254091725.962936 },
{ 2147483648,   43996705676.866089 }
};

//使用2分查找算法在logfac中 查找 x>=f 对应的下标
DWORD searchInLogFacTab1(double f)
{
DWORD low=0;
DWORD high=128;
DWORD mid;

while (true)
{
mid=(low+high)/2;
if ( mid==low)
{
while( logfac<f)
mid++;
break;
}
if ( f>=logfac )
{
low=mid;
}
else
{
high=mid;
}
}
return mid;
}

double getLogfac(DWORD n)
{
if (n<=128)
return logfac;
else
{
return LOGS2PI + ((double)n+0.5) * log(n)-n;
}
}

/*
求一个数x,使得满足 不等式 x! > 10^n的最小的值
   
   解方程 x!=10^n         (1)
   定义
c1= 0.5log(2pi)= 0.91893853320467274178032973640562
   c2= n* log(10)= n* 2.3025850929940456840179914546844


根据斯特林公式,有
   x!= sqrt(2*pi*x) * (x/e)^x (pi:为圆周率,e:自然对数的底)

方程左边取对数
log(x!) = log ( sqrt(2*pi*x)* (x/e)^x)
            = 0.5(log(x)+log(2pi))+ x(log(x)-1)
= (x+0.5)logx-x + 0.5log(2pi)
            = (x+0.5)logx-x + c1
   方程右边取对数
   log(10^n)= n * log(10)2.302585
            = c2
   
则原方程(1)化为 (x+0.5)logx-x + c1= c2   (2)
   
   定义:f(x)=log(x!)
   则有: f'(x)= 0.5+logx
   
   若 方程(2)的一个近似为x0,可导出牛顿迭代式:
      x1= x0 + ( c2 -f(x0))/f'(x)
       = x0 + ( c2- (x0+0.5)log(x0) +x0 - c1)/(0.5/x0+log(x0))
*/
// 解方程log(x!)=f,已知 low <= x <= high
// 返回x的值
DWORD faclogEquation(double f,int low,int high)
{
int i;

double x0,x1;
DWORD n;

if ( f <= logfac)
return searchInLogFacTab1(f);
x0= (low+high)/2;
#ifdef DEBUG_LOG_FAC
printf("---------\n");
printf("x0=%f\n",x0);
#endif
while(true)
{
x1= x0 + ( f- getLogfac((DWORD)x0))/(0.5/x0+log(x0));
#ifdef DEBUG_LOG_FAC
printf("x1=%f\n",x1);
#endif
if ( fabs(x1-x0)<0.75 )
break;
x0=x1;
}
#ifdef DEBUG_LOG_FAC
printf("---------\n");
#endif
if (x1<x0)
x0=x1;
n=(DWORD)x0;

while ( getLogfac(n) < f)
n++;
return n;
}

// 解方程log(x!)=f
// 返回x的值
DWORD faclogEquation(double f)
{
int i;
int low,high;

if ( f <= logfac)
return searchInLogFacTab1(f);

i=7;
while ( logfac_tab.logfac<f)
i++;
low= logfac_tab.n;
high=logfac_tab.n;
return faclogEquation(f,low,high);
}

liangbch 发表于 2008-4-17 10:50:32

回复15楼, 我刚才用刘楚雄的计算器计算了一下,计算100万位e值需要3.50秒,可能是他用的 ooura FFT 快于楼主的FNT.

liangbch 发表于 2008-4-17 10:52:36

回复22楼,如果频繁的使用 长整数乘以32位小整数,绝不会比9#算法更快。因为 大整数 乘以 单精度 整数没有快速算法,而大数乘以大数有快速算法。

无心人 发表于 2008-4-17 11:03:28

:lol

你竟然有这么奇怪的论调啊?

无心人 发表于 2008-4-17 11:09:52

另外
任何FFT均慢于最优化的NTT

FFT快, 说明HugeCalc的NTT算法不行
GxQ的NTT就是NTT+CRT
没利用好其他好的NTT
因为NTT算法有很多种
在不同情况下,各有优势

liangbch 发表于 2008-4-17 11:10:09

http://numbers.computation.free.fr/Constants 网站上给出一个计算任意位 e 的程序,其大整数乘法用FFT实现,FFT的代码非常简单(当然效率差点儿)。整个程序的代码量并不大,下面我贴出这个程序完整的代码。

文件 fft.h 的内容#ifndef FFT_h
#define FFT_h

typedef double Real;

extern double FFTSquareWorstError;
extern long AllocatedMemory;

void InitializeFFT(long MaxFFTLength);

void MulWithFFT(Real * ACoef, long ASize,
                Real * BCoef, long BSize,
                Real * CCoef);

#endif文件 BigInt.h的内容#ifndef BigInt_h
#define BigInt_h

#include "FFT.h"

typedef struct BigIntTag {
Real * Coef;
long Size, SizeMax;
} BigInt;

/*
* Decrease the base if the worst error in FFT become too large
*/
#define BASE 10000.
#define invBASE 0.0001
#define NBDEC_BASE 4

void InitializeBigInt(BigInt * A, long MaxSize);
void FreeBigInt(BigInt * A);

void PrintBigInt(BigInt * A);

void UpdateBigInt(BigInt * A);
void AddBigInt(BigInt * A, BigInt * B, BigInt * C);
void MulBigInt(BigInt * A, BigInt * B, BigInt * C);
void Inverse(BigInt * A, BigInt * B, BigInt * tmpBigInt);


#endifFFT.c 的内容/*
* Xavier Gourdon : Sept. 99 (xavier.gourdon.free.fr)
*
* FFT.c : Very basic FFT file.
*         The FFT encoded in this file is short and very basic.
*         It is just here as a teaching file to have a first
*         understanding of the FFT technique.
*         
* A lot of optimizations could be made to save a factor 2 or 4 for time
* and space.
*- Use a 4-Step (or more) FFT to avoid data cache misses.
*- Use an hermitian FFT to take into account the hermitian property of
*    the FFT of a real array.
*- Use a quad FFT (recursion N/4->N instead of N/2->N) to save 10 or
*    15% of the time.
*
*Informations can be found on
*    http://xavier.gourdon.free.fr/Constants/constants.html
*/
#include "FFT.h"

#include <stdlib.h>
#include <stdio.h>
#include <math.h>

#define PI 3.1415926535897932384626

typedef struct ComplexTag {
Real R,I;
} Complex;

long FFTLengthMax;
Complex * OmegaFFT;
Complex * ArrayFFT0, * ArrayFFT1;
Complex * ComplexCoef;
double FFTSquareWorstError;
long AllocatedMemory;

void InitializeFFT(long MaxLength)
{
long i;
Real Step;

FFTLengthMax = MaxLength;
OmegaFFT = (Complex *) malloc(MaxLength/2*sizeof(Complex));
ArrayFFT0 = (Complex *) malloc(MaxLength*sizeof(Complex));
ArrayFFT1 = (Complex *) malloc(MaxLength*sizeof(Complex));
ComplexCoef = (Complex *) malloc(MaxLength*sizeof(Complex));
Step = 2.*PI/(double) MaxLength;
for (i=0; 2*i<MaxLength; i++) {
    OmegaFFT.R = cos(Step*(double)i);
    OmegaFFT.I = sin(Step*(double)i);
}
FFTSquareWorstError=0.;
AllocatedMemory = 7*MaxLength*sizeof(Complex)/2;
}

void RecursiveFFT(Complex * Coef, Complex * FFT, long Length, long Step,
                  long Sign)
{
long i, OmegaStep;
Complex * FFT0, * FFT1, * Omega;
Real tmpR, tmpI;

if (Length==2) {
    FFT.R = Coef.R + Coef.R;
    FFT.I = Coef.I + Coef.I;
    FFT.R = Coef.R - Coef.R;
    FFT.I = Coef.I - Coef.I;
    return;
}

FFT0 = FFT;
RecursiveFFT(Coef   ,FFT0,Length/2,Step*2,Sign);
FFT1 = FFT+Length/2;
RecursiveFFT(Coef+Step,FFT1,Length/2,Step*2,Sign);

Omega = OmegaFFT;
OmegaStep = FFTLengthMax/Length;
for (i=0; 2*i<Length; i++, Omega += OmegaStep) {
    /* Recursion formula for FFT :
       FFT          <-FFT0 + Omega*FFT1
       FFT <-FFT0 - Omega*FFT1,
       Omega = exp(2*I*PI*i/Length) */
    tmpR = Omega.R*FFT1.R-Sign*Omega.I*FFT1.I;
    tmpI = Omega.R*FFT1.I+Sign*Omega.I*FFT1.R;
    FFT1.R = FFT0.R - tmpR;
    FFT1.I = FFT0.I - tmpI;
    FFT0.R = FFT0.R + tmpR;
    FFT0.I = FFT0.I + tmpI;
}
}

/* Compute the complex Fourier Transform of Coef into FFT */
void FFT(Real * Coef, long Length, Complex * FFT, long NFFT)
{
long i;
/* Transform array of real coefficient into array of complex */
for (i=0; i<Length; i++) {
    ComplexCoef.R = Coef;
    ComplexCoef.I = 0.;
}
for (; i<NFFT; i++)
    ComplexCoef.R = ComplexCoef.I = 0.;

RecursiveFFT(ComplexCoef,FFT,NFFT,1,1);
}

/* Compute the inverse Fourier Transform of FFT into Coef */
void InverseFFT(Complex * FFT, long NFFT, Real * Coef, long Length)
{
long i;
Real invNFFT = 1./(Real) NFFT, tmp;

RecursiveFFT(FFT, ComplexCoef, NFFT, 1, -1);
for (i=0; i<Length; i++) {
    /* Closest integer to ComplexCoef.R/NFFT */
    tmp = invNFFT*ComplexCoef.R;
    Coef = floor(0.5+tmp);
    if ((tmp-Coef)*(tmp-Coef)>FFTSquareWorstError)
      FFTSquareWorstError = (tmp-Coef)*(tmp-Coef);
}
}

void Convolution(Complex * A, Complex * B, long NFFT, Complex * C)
{
long i;
Real tmpR, tmpI;

for (i=0; i<NFFT; i++) {
   tmpR = A.R*B.R-A.I*B.I;
    tmpI = A.R*B.I+A.I*B.R;
    C.R = tmpR;
    C.I = tmpI;
}
}

void MulWithFFT(Real * ACoef, long ASize,
                Real * BCoef, long BSize,
                Real * CCoef)
{
long NFFT = 2;

while (NFFT<ASize+BSize)
    NFFT *= 2;

if (NFFT>FFTLengthMax) {
    printf("Error, FFT Size is too big in MulWithFFT\n");
    return;
}
FFT(ACoef, ASize, ArrayFFT0, NFFT);
FFT(BCoef, BSize, ArrayFFT1, NFFT);
Convolution(ArrayFFT0,ArrayFFT1,NFFT,ArrayFFT0);
InverseFFT(ArrayFFT0,NFFT,CCoef, ASize+BSize-1);
}BigInt.c的内容/*
* Xavier Gourdon : Sept. 99 (xavier.gourdon.free.fr)
*
* BigInt.c : Basic file for manipulation of Large Integers.
*            It rely on FFT.c to multiply number with the FFT
*            technique.
*         
* Several optimizations can be made :
*- Implementation of a classic multiplication for small BigInts.
*- Avoid using UpdateBigInt for the sum of BigInts.
*- Use a larger base for the internal data storage of BigInts to
*    save space.
*...
*
*Informations can be found on
*    http://xavier.gourdon.free.fr/Constants/constants.html
*/

#include "BigInt.h"
#include "FFT.h"

#include <math.h>
#include <stdlib.h>
#include <stdio.h>

void InitializeBigInt(BigInt * A, long MaxSize)
{
A->Coef = (Real *) malloc(MaxSize*sizeof(Real));
AllocatedMemory += MaxSize*sizeof(Real);

if (A->Coef==0)
    printf("Not enough memory\n");
A->Size = 0;
A->SizeMax = MaxSize;
}

void FreeBigInt(BigInt * A)
{
free(A->Coef);
}

void PrintBigInt(BigInt * A)
{
long i,j,Digit=0,Dec;
double Pow, Coef;

printf("%.0lf\n",A->Coef);

for (i=A->Size-2; i>=0; i--) {
    Pow = BASE*0.1;
    Coef = A->Coef;
    for (j=0; j<NBDEC_BASE; j++) {
      Dec = (long) (Coef/Pow);
      Coef -= Dec*Pow;
      Pow *= 0.1;
      printf("%ld",Dec);
      Digit++;
      if (Digit%10==0) printf(" ");
      if (Digit%50==0) printf(": %ld\n",Digit);
    }
}
}

/*
* Update A to the normal form (0<= A.Coef < BASE)
*/
void UpdateBigInt(BigInt * A)
{
long i;
Real carry=0., x;

for (i=0; i<A->Size; i++) {
    x = A->Coef + carry;
    carry = floor(x*invBASE);
    A->Coef = x-carry*BASE;
}
if (carry!=0) {
    while (carry!=0.) {
      x = carry;
      carry = floor(x*invBASE);
      A->Coef = x-carry*BASE;
      i++;
      A->Size=i;
    }
    if (A->Size > A->SizeMax) {
      printf("Error in UpdateBigInt, Size>SizeMax\n");
    }
}
else {
    while (i>0 && A->Coef==0.) i--;
    A->Size=i;
}
}

/*
* Compute C = A + B
*/
void AddBigInt(BigInt * A, BigInt * B, BigInt * C)
{
long i;

if (A->Size<B->Size) {
    AddBigInt(B,A,C);
    return;
}
/* We now have B->Size<A->Size */
for (i=0; i<B->Size; i++)
    C->Coef = A->Coef + B->Coef;
for (; i<A->Size; i++)
    C->Coef = A->Coef;

C->Size = A->Size;
UpdateBigInt(C);
}

/*
* Compute C = A*B
*/
void MulBigInt(BigInt * A, BigInt * B, BigInt * C)
{
MulWithFFT(A->Coef,A->Size,B->Coef,B->Size,C->Coef);
C->Size = A->Size+B->Size-1;
UpdateBigInt(C);
}

/*
* Compute the inverse of A in B
*/
void Inverse(BigInt * A, BigInt * B, BigInt * tmpBigInt)
{
double x;
long i, N,NN,Delta;
int Twice=1, Sign;
BigInt AA;

/* Initialization */
x = A->Coef+invBASE*(A->Coef
    + invBASE*A->Coef);
x = BASE/x;
B->Coef = floor(x);
B->Coef = floor((x-B->Coef)*BASE);
B->Size = 2;

/* Iteration used : B <- B+(1-AB)*B */
N=2;
while (N<A->Size) {
    /* Use only the first 2*N limbs of A */
    NN = 2*N;
    if (NN>A->Size)
      NN = A->Size;
    AA.Coef = A->Coef+A->Size-NN;
    AA.Size = NN;
    MulBigInt(&AA,B,tmpBigInt);
    Delta = NN+B->Size-1;
    /* Compute BASE^Delta-tmpBigInt in tmpBigInt */
    if (tmpBigInt->Size==Delta) {
      Sign=1;
      for (i=0; i<Delta; i++)
      tmpBigInt->Coef = BASE-1 - tmpBigInt->Coef;
      UpdateBigInt(tmpBigInt);
    }
    else {
      Sign = -1;
      tmpBigInt->Coef = 0.;
    }

    MulBigInt(tmpBigInt,B,tmpBigInt);
    for (i=0; i<tmpBigInt->Size-2*N+1; i++)
      tmpBigInt->Coef = tmpBigInt->Coef;
    tmpBigInt->Size -= 2*N-1;
    for (i=B->Size-1; i>=0; i--)
      B->Coef = B->Coef;
    for (i=NN-N-1; i>=0; i--)
      B->Coef=0.;
    B->Size += NN-N;
    if (Sign==-1) {
      for (i=0; i<tmpBigInt->Size; i++)
      tmpBigInt->Coef = -tmpBigInt->Coef;
    }
    AddBigInt(B,tmpBigInt,B);
    /* Once during the process, redo one iteration with same precision */
    if (8*N>A->Size && Twice) {
      Twice=0;
      B->Size = N;
      for (i=0; i<N; i++)
      B->Coef = B->Coef;
    }
    else
      N *= 2;
}
}主程序(e.c)的内容/*
* Xavier Gourdon : Sept. 99 (xavier.gourdon.free.fr)
*
* e.c : Basic file for computation of e=2.7181... with the binary
*       splitting method.
*       It relies on the files FFT.c and BigInt.c to handle
*       Large Integers.
*         
* Several optimizations can be made :
*- Use a specialized routine to handle binary splitting when the
*    indexes are close.
*...
*
*Informations can be found on
*    http://xavier.gourdon.free.fr/Constants/constants.html
*/

#include "FFT.h"
#include "BigInt.h"

#include <stdio.h>
#include <math.h>
#include <time.h>

BigInt tmpBigInt; /* Temporary BigInt used in the binary splitting */

/*
* Compute the numerator P and denominator Q of
* P/Q = 1/(N0+1) + 1/(N0+1)/(N0+2) + ... + 1/(N0+1)/.../N1
*/
void BinarySplittingE(long N0, long N1, BigInt * P, BigInt * Q)
{
BigInt PP, QQ;
long NMid;

if (N1-N0==1) {
    P->Size = Q->Size = 1;
    P->Coef = 1.;
    Q->Coef = (double) N1;
    UpdateBigInt(P);
    UpdateBigInt(Q);
    return;
}
NMid = (N0+N1)/2;
BinarySplittingE(N0,NMid,P,Q);
/* To save memory, take the non used coefficients of P and Q
   for coefficient of the BigInt used in the second splitting part */
PP.Coef = P->Coef + P->Size;
PP.SizeMax = P->SizeMax-P->Size;
QQ.Coef = Q->Coef + Q->Size;
QQ.SizeMax = Q->SizeMax-Q->Size;

BinarySplittingE(NMid,N1,&PP,&QQ);
MulBigInt(P,&QQ,&tmpBigInt);
AddBigInt(&tmpBigInt,&PP,P);

MulBigInt(Q,&QQ,Q);
}

/*
* Returns as a BigInt the constant E with NbDec decimal digits
*/
BigInt ECompute(long NbDec)
{
BigInt P, Q, tmp;
long i, MaxSize, MaxFFTSize, SeriesSize;
double logFactorial, logMax;

/* MaxSize should be more than NbDec/NBDEC_BASE (see BinarySplitting) */
MaxSize = NbDec/NBDEC_BASE + 10 + (long) (2.*log((double)NbDec)/log(2.));
InitializeBigInt(&P,MaxSize);
InitializeBigInt(&Q,MaxSize);

MaxFFTSize = 2;
while (MaxFFTSize < MaxSize)
    MaxFFTSize *= 2;
MaxFFTSize *= 2;
InitializeFFT(MaxFFTSize);
/* Temporary BigInts are needed */
InitializeBigInt(&tmpBigInt,MaxFFTSize);
InitializeBigInt(&tmp,MaxFFTSize);

printf("Total Allocated memory = %ld K\n",AllocatedMemory/1024);

/* Compute the number of term SeriesSize of the series required.
   SeriesSize is such that log(SeriesSize !) > NbDec*log(10.) */
SeriesSize=1;
logFactorial=0.;
logMax = (double)NbDec * log(10.);
while (logFactorial<logMax) {
    logFactorial += log((double) SeriesSize);
    SeriesSize++;
}

printf("Starting series computation\n");
/* Compute the numerator P and the denominator Q of
   sum_{i=0}^{SeriesSize} 1/i! */
BinarySplittingE(0,SeriesSize,&P,&Q);
AddBigInt(&P,&Q,&P);

printf("Starting final division\n");
/* Compute the inverse of Q in tmpBigInt */
Inverse(&Q,&tmpBigInt,&tmp);
/* Comute P/Q in tmpBigInt */
MulBigInt(&P,&tmpBigInt,&tmpBigInt);

/* Put the number of required digits in P */
P.Size = 1+NbDec/NBDEC_BASE;
for (i=1; i<=P.Size; i++)
    P.Coef = tmpBigInt.Coef;

FreeBigInt(&Q);
FreeBigInt(&tmpBigInt);

return P;
}


void main()
{
double StartTime;
BigInt E;
long NbDec;

printf("*** E computation *** \n\n");
printf("Enter the number of decimal digits : ");
scanf("%ld",&NbDec);
printf("\n");
StartTime = (double) clock();
E = ECompute(NbDec);
printf("\n");
printf("Total time : %.2lf seconds\n",((double) clock() - StartTime)/CLOCKS_PER_SEC);
printf("Worst error in FFT (should be less than 0.25): %.10lf\n",sqrt(FFTSquareWorstError));
printf("\n");
printf("E = ");
//PrintBigInt(&E);
printf("\n");
}

shshsh_0510 发表于 2008-4-17 11:12:59

呵呵,借用李白观黄鹤楼的感慨:眼前有景道不得,liangbch程序在上头
只剩学习了

无心人 发表于 2008-4-17 11:14:20

我有一种感觉
计算e的算法效率远不如计算pi
页: 1 2 [3] 4 5 6 7 8 9 10 11 12
查看完整版本: 计算百万位e