找回密码
 欢迎注册
楼主: liangbch

[擂台] 计算百万位e

[复制链接]
发表于 2008-4-17 08:38:27 | 显示全部楼层
呵呵,liangbch已经给出了
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2008-4-17 08:51:56 | 显示全部楼层


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

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

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

具体算法俺已从他给出网页整理到19#
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2008-4-17 10:39:46 | 显示全部楼层
回复 17楼 mathe.
求 x,使得 $ log10(x!)=n $有更有效的算法,只是这部分代码占用的时间很小,我在之前的代码中没有给出更有效更复杂的代码。

下面贴出代码:
  函数 faclogEquation(double f) 返回 方程 $log10(x!)=f $ 的解
  1. #define  PI 3.1415926535897932384626433832795   
  2. #define  LOG10 2.3025850929940456840179914546844
  3. #define  LOGS2PI 0.91893853320467274178032973640562   //log(sqrt(2*pi))
  4. typedef unsigned long DWORD;

  5. typedef struct _logfacpair
  6. {
  7. unsigned long n;
  8. double logfac;
  9. }LOGFAC_PAIR;

  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <math.h>
  13. #include <assert.h>
  14. /*
  15. 计算e,使用HugeCalc,一个简单的版本
  16. */
  17. //#define DEBUG_LOG_FAC

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

  150. const LOGFAC_PAIR logfac_tab[]=
  151. {
  152. {          1,   0.000000 },
  153. {          2,   0.693147 },
  154. {          4,   3.178054 },
  155. {          8,   10.604603 },
  156. {         16,   30.671860 },
  157. {         32,   81.557959 },
  158. {         64,   205.168199 },
  159. {        128,   496.405478 },
  160. {        256,   1167.256953 },
  161. {        512,   2686.060309 },
  162. {       1024,   6078.211803 },
  163. {       2048,   13571.950932 },
  164. {       4096,   29978.648040 },
  165. {       8192,   65630.826536 },
  166. {      16384,   142613.098657 },
  167. {      32768,   307933.819731 },
  168. {      65536,   661287.962119 },
  169. {     131072,   1413421.993946 },
  170. {     262144,   3008541.898276 },
  171. {     524288,   6380485.734864 },
  172. {    1048576,   13487781.810467 },
  173. {    2097152,   28429191.113103 },
  174. {    4194304,   59765644.367806 },
  175. {    8388608,   125345820.522651 },
  176. {   16777216,   262320712.469790 },
  177. {   33554432,   547899575.985538 },
  178. {   67108864,   1142315462.606553 },
  179. {  134217728,   2377663555.374189 },
  180. {  268435456,   4941392380.307250 },
  181. {  536870912,   10254915309.315521 },
  182. { 1073741824,   21254091725.962936 },
  183. { 2147483648,   43996705676.866089 }
  184. };

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

  191. while (true)
  192. {
  193. mid=(low+high)/2;
  194. if ( mid==low)
  195. {
  196. while( logfac[mid]<f)
  197. mid++;
  198. break;
  199. }
  200. if ( f>=logfac[mid] )
  201. {
  202. low=mid;
  203. }
  204. else
  205. {
  206. high=mid;
  207. }
  208. }
  209. return mid;
  210. }

  211. double getLogfac(DWORD n)
  212. {
  213. if (n<=128)
  214. return logfac[n];
  215. else
  216. {
  217. return LOGS2PI + ((double)n+0.5) * log(n)-n;
  218. }
  219. }

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

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

  230.   方程左边取对数
  231.   log(x!) = log ( sqrt(2*pi*x)* (x/e)^x)
  232.             = 0.5(log(x)+log(2pi))+ x(log(x)-1)
  233. = (x+0.5)logx-x + 0.5log(2pi)
  234.             = (x+0.5)logx-x + c1
  235.    方程右边取对数
  236.      log(10^n)= n * log(10)2.302585
  237.             = c2
  238.    
  239.   则原方程(1)化为 (x+0.5)logx-x + c1= c2   (2)
  240.    
  241.    定义:f(x)=log(x!)
  242.    则有: f'(x)= 0.5+logx
  243.    
  244.    若 方程(2)的一个近似为x0,可导出牛顿迭代式:
  245.       x1= x0 + ( c2 -f(x0))/f'(x)
  246.        = x0 + ( c2- (x0+0.5)log(x0) +x0 - c1)/(0.5/x0+log(x0))
  247. */
  248. // 解方程log(x!)=f,已知 low <= x <= high
  249. // 返回x的值
  250. DWORD faclogEquation(double f,int low,int high)
  251. {
  252. int i;

  253. double x0,x1;
  254. DWORD n;

  255. if ( f <= logfac[128])
  256. return searchInLogFacTab1(f);
  257. x0= (low+high)/2;
  258. #ifdef DEBUG_LOG_FAC
  259. printf("---------\n");
  260. printf("x0=%f\n",x0);
  261. #endif
  262. while(true)
  263. {
  264. x1= x0 + ( f- getLogfac((DWORD)x0))/(0.5/x0+log(x0));
  265. #ifdef DEBUG_LOG_FAC
  266. printf("x1=%f\n",x1);
  267. #endif
  268. if ( fabs(x1-x0)<0.75 )
  269. break;
  270. x0=x1;
  271. }
  272. #ifdef DEBUG_LOG_FAC
  273. printf("---------\n");
  274. #endif
  275. if (x1<x0)
  276. x0=x1;
  277. n=(DWORD)x0;

  278. while ( getLogfac(n) < f)
  279. n++;
  280. return n;
  281. }

  282. // 解方程log(x!)=f
  283. // 返回x的值
  284. DWORD faclogEquation(double f)
  285. {
  286. int i;
  287. int low,high;

  288. if ( f <= logfac[128])
  289. return searchInLogFacTab1(f);

  290. i=7;
  291. while ( logfac_tab[i].logfac<f)
  292. i++;
  293. low= logfac_tab[i-1].n;
  294. high=logfac_tab[i].n;
  295. return faclogEquation(f,low,high);
  296. }
复制代码
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2008-4-17 10:50:32 | 显示全部楼层
回复15楼, 我刚才用刘楚雄的计算器计算了一下,计算100万位e值需要3.50秒,可能是他用的 ooura FFT 快于楼主的FNT.
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2008-4-17 10:52:36 | 显示全部楼层
回复22楼,如果频繁的使用 长整数乘以32位小整数,绝不会比9#算法更快。因为 大整数 乘以 单精度 整数没有快速算法,而大数乘以大数有快速算法。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2008-4-17 11:03:28 | 显示全部楼层


你竟然有这么奇怪的论调啊?
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2008-4-17 11:09:52 | 显示全部楼层
另外
任何FFT均慢于最优化的NTT

FFT快, 说明HugeCalc的NTT算法不行
GxQ的NTT就是NTT+CRT
没利用好其他好的NTT
因为NTT算法有很多种
在不同情况下,各有优势
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2008-4-17 11:10:09 | 显示全部楼层
http://numbers.computation.free.fr/Constants 网站上给出一个计算任意位 e 的程序,其大整数乘法用FFT实现,FFT的代码非常简单(当然效率差点儿)。整个程序的代码量并不大,下面我贴出这个程序完整的代码。

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

  3. typedef double Real;

  4. extern double FFTSquareWorstError;
  5. extern long AllocatedMemory;

  6. void InitializeFFT(long MaxFFTLength);

  7. void MulWithFFT(Real * ACoef, long ASize,
  8.                 Real * BCoef, long BSize,
  9.                 Real * CCoef);

  10. #endif
复制代码
文件 BigInt.h的内容
  1. #ifndef BigInt_h
  2. #define BigInt_h

  3. #include "FFT.h"

  4. typedef struct BigIntTag {
  5.   Real * Coef;
  6.   long Size, SizeMax;
  7. } BigInt;

  8. /*
  9. * Decrease the base if the worst error in FFT become too large
  10. */
  11. #define BASE 10000.
  12. #define invBASE 0.0001
  13. #define NBDEC_BASE 4

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

  16. void PrintBigInt(BigInt * A);

  17. void UpdateBigInt(BigInt * A);
  18. void AddBigInt(BigInt * A, BigInt * B, BigInt * C);
  19. void MulBigInt(BigInt * A, BigInt * B, BigInt * C);
  20. void Inverse(BigInt * A, BigInt * B, BigInt * tmpBigInt);


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

  21. #include <stdlib.h>
  22. #include <stdio.h>
  23. #include <math.h>

  24. #define PI 3.1415926535897932384626

  25. typedef struct ComplexTag {
  26.   Real R,I;
  27. } Complex;

  28. long FFTLengthMax;
  29. Complex * OmegaFFT;
  30. Complex * ArrayFFT0, * ArrayFFT1;
  31. Complex * ComplexCoef;
  32. double FFTSquareWorstError;
  33. long AllocatedMemory;

  34. void InitializeFFT(long MaxLength)
  35. {
  36.   long i;
  37.   Real Step;

  38.   FFTLengthMax = MaxLength;
  39.   OmegaFFT = (Complex *) malloc(MaxLength/2*sizeof(Complex));
  40.   ArrayFFT0 = (Complex *) malloc(MaxLength*sizeof(Complex));
  41.   ArrayFFT1 = (Complex *) malloc(MaxLength*sizeof(Complex));
  42.   ComplexCoef = (Complex *) malloc(MaxLength*sizeof(Complex));
  43.   Step = 2.*PI/(double) MaxLength;
  44.   for (i=0; 2*i<MaxLength; i++) {
  45.     OmegaFFT[i].R = cos(Step*(double)i);
  46.     OmegaFFT[i].I = sin(Step*(double)i);
  47.   }
  48.   FFTSquareWorstError=0.;
  49.   AllocatedMemory = 7*MaxLength*sizeof(Complex)/2;
  50. }

  51. void RecursiveFFT(Complex * Coef, Complex * FFT, long Length, long Step,
  52.                   long Sign)
  53. {
  54.   long i, OmegaStep;
  55.   Complex * FFT0, * FFT1, * Omega;
  56.   Real tmpR, tmpI;

  57.   if (Length==2) {
  58.     FFT[0].R = Coef[0].R + Coef[Step].R;
  59.     FFT[0].I = Coef[0].I + Coef[Step].I;
  60.     FFT[1].R = Coef[0].R - Coef[Step].R;
  61.     FFT[1].I = Coef[0].I - Coef[Step].I;
  62.     return;
  63.   }

  64.   FFT0 = FFT;
  65.   RecursiveFFT(Coef     ,FFT0,Length/2,Step*2,Sign);
  66.   FFT1 = FFT+Length/2;
  67.   RecursiveFFT(Coef+Step,FFT1,Length/2,Step*2,Sign);

  68.   Omega = OmegaFFT;
  69.   OmegaStep = FFTLengthMax/Length;
  70.   for (i=0; 2*i<Length; i++, Omega += OmegaStep) {
  71.     /* Recursion formula for FFT :
  72.        FFT[i]          <-  FFT0[i] + Omega*FFT1[i]
  73.        FFT[i+Length/2] <-  FFT0[i] - Omega*FFT1[i],
  74.        Omega = exp(2*I*PI*i/Length) */
  75.     tmpR = Omega[0].R*FFT1[i].R-Sign*Omega[0].I*FFT1[i].I;
  76.     tmpI = Omega[0].R*FFT1[i].I+Sign*Omega[0].I*FFT1[i].R;
  77.     FFT1[i].R = FFT0[i].R - tmpR;
  78.     FFT1[i].I = FFT0[i].I - tmpI;
  79.     FFT0[i].R = FFT0[i].R + tmpR;
  80.     FFT0[i].I = FFT0[i].I + tmpI;
  81.   }
  82. }

  83. /* Compute the complex Fourier Transform of Coef into FFT */
  84. void FFT(Real * Coef, long Length, Complex * FFT, long NFFT)
  85. {
  86.   long i;
  87.   /* Transform array of real coefficient into array of complex */
  88.   for (i=0; i<Length; i++) {
  89.     ComplexCoef[i].R = Coef[i];
  90.     ComplexCoef[i].I = 0.;
  91.   }
  92.   for (; i<NFFT; i++)
  93.     ComplexCoef[i].R = ComplexCoef[i].I = 0.;

  94.   RecursiveFFT(ComplexCoef,FFT,NFFT,1,1);
  95. }

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

  101.   RecursiveFFT(FFT, ComplexCoef, NFFT, 1, -1);
  102.   for (i=0; i<Length; i++) {
  103.     /* Closest integer to ComplexCoef[i].R/NFFT */
  104.     tmp = invNFFT*ComplexCoef[i].R;
  105.     Coef[i] = floor(0.5+tmp);
  106.     if ((tmp-Coef[i])*(tmp-Coef[i])>FFTSquareWorstError)
  107.       FFTSquareWorstError = (tmp-Coef[i])*(tmp-Coef[i]);
  108.   }
  109. }

  110. void Convolution(Complex * A, Complex * B, long NFFT, Complex * C)
  111. {
  112.   long i;
  113.   Real tmpR, tmpI;

  114.   for (i=0; i<NFFT; i++) {
  115.    tmpR = A[i].R*B[i].R-A[i].I*B[i].I;
  116.     tmpI = A[i].R*B[i].I+A[i].I*B[i].R;
  117.     C[i].R = tmpR;
  118.     C[i].I = tmpI;
  119.   }
  120. }

  121. void MulWithFFT(Real * ACoef, long ASize,
  122.                 Real * BCoef, long BSize,
  123.                 Real * CCoef)
  124. {
  125.   long NFFT = 2;

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

  128.   if (NFFT>FFTLengthMax) {
  129.     printf("Error, FFT Size is too big in MulWithFFT\n");
  130.     return;
  131.   }
  132.   FFT(ACoef, ASize, ArrayFFT0, NFFT);
  133.   FFT(BCoef, BSize, ArrayFFT1, NFFT);
  134.   Convolution(ArrayFFT0,ArrayFFT1,NFFT,ArrayFFT0);
  135.   InverseFFT(ArrayFFT0,NFFT,CCoef, ASize+BSize-1);
  136. }
复制代码
BigInt.c的内容
  1. /*
  2. * Xavier Gourdon : Sept. 99 (xavier.gourdon.free.fr)
  3. *
  4. * BigInt.c : Basic file for manipulation of Large Integers.
  5. *            It rely on FFT.c to multiply number with the FFT
  6. *            technique.
  7. *         
  8. * Several optimizations can be made :
  9. *  - Implementation of a classic multiplication for small BigInts.
  10. *  - Avoid using UpdateBigInt for the sum of BigInts.
  11. *  - Use a larger base for the internal data storage of BigInts to
  12. *    save space.
  13. *  ...
  14. *
  15. *  Informations can be found on
  16. *    http://xavier.gourdon.free.fr/Constants/constants.html
  17. */

  18. #include "BigInt.h"
  19. #include "FFT.h"

  20. #include <math.h>
  21. #include <stdlib.h>
  22. #include <stdio.h>

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

  27.   if (A->Coef==0)
  28.     printf("Not enough memory\n");
  29.   A->Size = 0;
  30.   A->SizeMax = MaxSize;
  31. }

  32. void FreeBigInt(BigInt * A)
  33. {
  34.   free(A->Coef);
  35. }

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

  40.   printf("%.0lf\n",A->Coef[A->Size-1]);

  41.   for (i=A->Size-2; i>=0; i--) {
  42.     Pow = BASE*0.1;
  43.     Coef = A->Coef[i];
  44.     for (j=0; j<NBDEC_BASE; j++) {
  45.       Dec = (long) (Coef/Pow);
  46.       Coef -= Dec*Pow;
  47.       Pow *= 0.1;
  48.       printf("%ld",Dec);
  49.       Digit++;
  50.       if (Digit%10==0) printf(" ");
  51.       if (Digit%50==0) printf(": %ld\n",Digit);
  52.     }
  53.   }
  54. }

  55. /*
  56. * Update A to the normal form (0<= A.Coef[i] < BASE)
  57. */
  58. void UpdateBigInt(BigInt * A)
  59. {
  60.   long i;
  61.   Real carry=0., x;

  62.   for (i=0; i<A->Size; i++) {
  63.     x = A->Coef[i] + carry;
  64.     carry = floor(x*invBASE);
  65.     A->Coef[i] = x-carry*BASE;
  66.   }
  67.   if (carry!=0) {
  68.     while (carry!=0.) {
  69.       x = carry;
  70.       carry = floor(x*invBASE);
  71.       A->Coef[i] = x-carry*BASE;
  72.       i++;
  73.       A->Size=i;
  74.     }
  75.     if (A->Size > A->SizeMax) {
  76.       printf("Error in UpdateBigInt, Size>SizeMax\n");
  77.     }
  78.   }
  79.   else {
  80.     while (i>0 && A->Coef[i-1]==0.) i--;
  81.     A->Size=i;
  82.   }
  83. }

  84. /*
  85. * Compute C = A + B
  86. */
  87. void AddBigInt(BigInt * A, BigInt * B, BigInt * C)
  88. {
  89.   long i;

  90.   if (A->Size<B->Size) {
  91.     AddBigInt(B,A,C);
  92.     return;
  93.   }
  94.   /* We now have B->Size<A->Size */
  95.   for (i=0; i<B->Size; i++)
  96.     C->Coef[i] = A->Coef[i] + B->Coef[i];
  97.   for (; i<A->Size; i++)
  98.     C->Coef[i] = A->Coef[i];

  99.   C->Size = A->Size;
  100.   UpdateBigInt(C);
  101. }

  102. /*
  103. * Compute C = A*B
  104. */
  105. void MulBigInt(BigInt * A, BigInt * B, BigInt * C)
  106. {
  107.   MulWithFFT(A->Coef,A->Size,B->Coef,B->Size,C->Coef);
  108.   C->Size = A->Size+B->Size-1;
  109.   UpdateBigInt(C);
  110. }

  111. /*
  112. * Compute the inverse of A in B
  113. */
  114. void Inverse(BigInt * A, BigInt * B, BigInt * tmpBigInt)
  115. {
  116.   double x;
  117.   long i, N,NN,Delta;
  118.   int Twice=1, Sign;
  119.   BigInt AA;

  120.   /* Initialization */
  121.   x = A->Coef[A->Size-1]+invBASE*(A->Coef[A->Size-2]
  122.     + invBASE*A->Coef[A->Size-3]);
  123.   x = BASE/x;
  124.   B->Coef[1] = floor(x);
  125.   B->Coef[0] = floor((x-B->Coef[1])*BASE);
  126.   B->Size = 2;

  127.   /* Iteration used : B <- B+(1-AB)*B */
  128.   N=2;
  129.   while (N<A->Size) {
  130.     /* Use only the first 2*N limbs of A */
  131.     NN = 2*N;
  132.     if (NN>A->Size)
  133.       NN = A->Size;
  134.     AA.Coef = A->Coef+A->Size-NN;
  135.     AA.Size = NN;
  136.     MulBigInt(&AA,B,tmpBigInt);
  137.     Delta = NN+B->Size-1;
  138.     /* Compute BASE^Delta-tmpBigInt in tmpBigInt */
  139.     if (tmpBigInt->Size==Delta) {
  140.       Sign=1;
  141.       for (i=0; i<Delta; i++)
  142.         tmpBigInt->Coef[i] = BASE-1 - tmpBigInt->Coef[i];
  143.       UpdateBigInt(tmpBigInt);
  144.     }
  145.     else {
  146.       Sign = -1;
  147.       tmpBigInt->Coef[Delta] = 0.;
  148.     }

  149.     MulBigInt(tmpBigInt,B,tmpBigInt);
  150.     for (i=0; i<tmpBigInt->Size-2*N+1; i++)
  151.       tmpBigInt->Coef[i] = tmpBigInt->Coef[i+2*N-1];
  152.     tmpBigInt->Size -= 2*N-1;
  153.     for (i=B->Size-1; i>=0; i--)
  154.       B->Coef[i+NN-N] = B->Coef[i];
  155.     for (i=NN-N-1; i>=0; i--)
  156.       B->Coef[i]=0.;
  157.     B->Size += NN-N;
  158.     if (Sign==-1) {
  159.       for (i=0; i<tmpBigInt->Size; i++)
  160.         tmpBigInt->Coef[i] = -tmpBigInt->Coef[i];
  161.     }
  162.     AddBigInt(B,tmpBigInt,B);
  163.     /* Once during the process, redo one iteration with same precision */
  164.     if (8*N>A->Size && Twice) {
  165.       Twice=0;
  166.       B->Size = N;
  167.       for (i=0; i<N; i++)
  168.         B->Coef[i] = B->Coef[i+N];
  169.     }
  170.     else
  171.       N *= 2;
  172.   }
  173. }
复制代码
主程序(e.c)的内容
  1. /*
  2. * Xavier Gourdon : Sept. 99 (xavier.gourdon.free.fr)
  3. *
  4. * e.c : Basic file for computation of e=2.7181... with the binary
  5. *       splitting method.
  6. *       It relies on the files FFT.c and BigInt.c to handle
  7. *       Large Integers.
  8. *         
  9. * Several optimizations can be made :
  10. *  - Use a specialized routine to handle binary splitting when the
  11. *    indexes are close.
  12. *  ...
  13. *
  14. *  Informations can be found on
  15. *    http://xavier.gourdon.free.fr/Constants/constants.html
  16. */

  17. #include "FFT.h"
  18. #include "BigInt.h"

  19. #include <stdio.h>
  20. #include <math.h>
  21. #include <time.h>

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

  23. /*
  24. * Compute the numerator P and denominator Q of
  25. * P/Q = 1/(N0+1) + 1/(N0+1)/(N0+2) + ... + 1/(N0+1)/.../N1
  26. */
  27. void BinarySplittingE(long N0, long N1, BigInt * P, BigInt * Q)
  28. {
  29.   BigInt PP, QQ;
  30.   long NMid;

  31.   if (N1-N0==1) {
  32.     P->Size = Q->Size = 1;
  33.     P->Coef[0] = 1.;
  34.     Q->Coef[0] = (double) N1;
  35.     UpdateBigInt(P);
  36.     UpdateBigInt(Q);
  37.     return;
  38.   }
  39.   NMid = (N0+N1)/2;
  40.   BinarySplittingE(N0,NMid,P,Q);
  41.   /* To save memory, take the non used coefficients of P and Q
  42.      for coefficient of the BigInt used in the second splitting part */
  43.   PP.Coef = P->Coef + P->Size;
  44.   PP.SizeMax = P->SizeMax-P->Size;
  45.   QQ.Coef = Q->Coef + Q->Size;
  46.   QQ.SizeMax = Q->SizeMax-Q->Size;

  47.   BinarySplittingE(NMid,N1,&PP,&QQ);
  48.   MulBigInt(P,&QQ,&tmpBigInt);
  49.   AddBigInt(&tmpBigInt,&PP,P);

  50.   MulBigInt(Q,&QQ,Q);
  51. }

  52. /*
  53. * Returns as a BigInt the constant E with NbDec decimal digits
  54. */
  55. BigInt ECompute(long NbDec)
  56. {
  57.   BigInt P, Q, tmp;
  58.   long i, MaxSize, MaxFFTSize, SeriesSize;
  59.   double logFactorial, logMax;

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

  64.   MaxFFTSize = 2;
  65.   while (MaxFFTSize < MaxSize)
  66.     MaxFFTSize *= 2;
  67.   MaxFFTSize *= 2;
  68.   InitializeFFT(MaxFFTSize);
  69.   /* Temporary BigInts are needed */
  70.   InitializeBigInt(&tmpBigInt,MaxFFTSize);
  71.   InitializeBigInt(&tmp,MaxFFTSize);

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

  73.   /* Compute the number of term SeriesSize of the series required.
  74.      SeriesSize is such that log(SeriesSize !) > NbDec*log(10.) */
  75.   SeriesSize=1;
  76.   logFactorial=0.;
  77.   logMax = (double)NbDec * log(10.);
  78.   while (logFactorial<logMax) {
  79.     logFactorial += log((double) SeriesSize);
  80.     SeriesSize++;
  81.   }

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

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

  92.   /* Put the number of required digits in P */
  93.   P.Size = 1+NbDec/NBDEC_BASE;
  94.   for (i=1; i<=P.Size; i++)
  95.     P.Coef[P.Size-i] = tmpBigInt.Coef[tmpBigInt.Size-i];
  96.   
  97.   FreeBigInt(&Q);
  98.   FreeBigInt(&tmpBigInt);

  99.   return P;
  100. }


  101. void main()
  102. {
  103.   double StartTime;
  104.   BigInt E;
  105.   long NbDec;
  106.   
  107.   printf("*** E computation *** \n\n");
  108.   printf("Enter the number of decimal digits : ");
  109.   scanf("%ld",&NbDec);
  110.   printf("\n");
  111.   StartTime = (double) clock();
  112.   E = ECompute(NbDec);
  113.   printf("\n");
  114.   printf("Total time : %.2lf seconds\n",((double) clock() - StartTime)/CLOCKS_PER_SEC);
  115.   printf("Worst error in FFT (should be less than 0.25): %.10lf\n",sqrt(FFTSquareWorstError));
  116.   printf("\n");
  117.   printf("E = ");
  118.   //PrintBigInt(&E);
  119.   printf("\n");
  120. }
复制代码
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2008-4-17 11:12:59 | 显示全部楼层
呵呵,借用李白观黄鹤楼的感慨:眼前有景道不得,liangbch程序在上头
只剩学习了
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2008-4-17 11:14:20 | 显示全部楼层
我有一种感觉
计算e的算法效率远不如计算pi
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
您需要登录后才可以回帖 登录 | 欢迎注册

本版积分规则

小黑屋|手机版|数学研发网 ( 苏ICP备07505100号 )

GMT+8, 2024-4-20 20:46 , Processed in 0.044371 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表