找回密码
 欢迎注册
楼主: 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. 解方程 x!=10^n (1)
  223. 定义
  224. c1= 0.5log(2pi)= 0.91893853320467274178032973640562
  225. c2= n* log(10)= n* 2.3025850929940456840179914546844
  226. 根据斯特林公式,有
  227. x!= sqrt(2*pi*x) * (x/e)^x (pi:为圆周率,e:自然对数的底)
  228. 方程左边取对数
  229. log(x!) = log ( sqrt(2*pi*x)* (x/e)^x)
  230. = 0.5(log(x)+log(2pi))+ x(log(x)-1)
  231. = (x+0.5)logx-x + 0.5log(2pi)
  232. = (x+0.5)logx-x + c1
  233. 方程右边取对数
  234. log(10^n)= n * log(10)2.302585
  235. = c2
  236. 则原方程(1)化为 (x+0.5)logx-x + c1= c2 (2)
  237. 定义:f(x)=log(x!)
  238. 则有: f'(x)= 0.5+logx
  239. 若 方程(2)的一个近似为x0,可导出牛顿迭代式:
  240. x1= x0 + ( c2 -f(x0))/f'(x)
  241. = x0 + ( c2- (x0+0.5)log(x0) +x0 - c1)/(0.5/x0+log(x0))
  242. */
  243. // 解方程log(x!)=f,已知 low <= x <= high
  244. // 返回x的值
  245. DWORD faclogEquation(double f,int low,int high)
  246. {
  247. int i;
  248. double x0,x1;
  249. DWORD n;
  250. if ( f <= logfac[128])
  251. return searchInLogFacTab1(f);
  252. x0= (low+high)/2;
  253. #ifdef DEBUG_LOG_FAC
  254. printf("---------\n");
  255. printf("x0=%f\n",x0);
  256. #endif
  257. while(true)
  258. {
  259. x1= x0 + ( f- getLogfac((DWORD)x0))/(0.5/x0+log(x0));
  260. #ifdef DEBUG_LOG_FAC
  261. printf("x1=%f\n",x1);
  262. #endif
  263. if ( fabs(x1-x0)<0.75 )
  264. break;
  265. x0=x1;
  266. }
  267. #ifdef DEBUG_LOG_FAC
  268. printf("---------\n");
  269. #endif
  270. if (x1<x0)
  271. x0=x1;
  272. n=(DWORD)x0;
  273. while ( getLogfac(n) < f)
  274. n++;
  275. return n;
  276. }
  277. // 解方程log(x!)=f
  278. // 返回x的值
  279. DWORD faclogEquation(double f)
  280. {
  281. int i;
  282. int low,high;
  283. if ( f <= logfac[128])
  284. return searchInLogFacTab1(f);
  285. i=7;
  286. while ( logfac_tab[i].logfac<f)
  287. i++;
  288. low= logfac_tab[i-1].n;
  289. high=logfac_tab[i].n;
  290. return faclogEquation(f,low,high);
  291. }
复制代码
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 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. FreeBigInt(&Q);
  97. FreeBigInt(&tmpBigInt);
  98. return P;
  99. }
  100. void main()
  101. {
  102. double StartTime;
  103. BigInt E;
  104. long NbDec;
  105. printf("*** E computation *** \n\n");
  106. printf("Enter the number of decimal digits : ");
  107. scanf("%ld",&NbDec);
  108. printf("\n");
  109. StartTime = (double) clock();
  110. E = ECompute(NbDec);
  111. printf("\n");
  112. printf("Total time : %.2lf seconds\n",((double) clock() - StartTime)/CLOCKS_PER_SEC);
  113. printf("Worst error in FFT (should be less than 0.25): %.10lf\n",sqrt(FFTSquareWorstError));
  114. printf("\n");
  115. printf("E = ");
  116. //PrintBigInt(&E);
  117. printf("\n");
  118. }
复制代码
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2008-4-17 11:12:59 | 显示全部楼层
呵呵,借用李白观黄鹤楼的感慨:眼前有景道不得,liangbch程序在上头 只剩学习了
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2008-4-17 11:14:20 | 显示全部楼层
我有一种感觉 计算e的算法效率远不如计算pi
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
您需要登录后才可以回帖 登录 | 欢迎注册

本版积分规则

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

GMT+8, 2024-11-23 16:06 , Processed in 0.044094 second(s), 21 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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