- 注册时间
- 2007-12-28
- 最后登录
- 1970-1-1
- 威望
- 星
- 金币
- 枚
- 贡献
- 分
- 经验
- 点
- 鲜花
- 朵
- 魅力
- 点
- 上传
- 次
- 下载
- 次
- 积分
- 12785
- 在线时间
- 小时
|
楼主 |
发表于 2008-4-17 10:39:46
|
显示全部楼层
回复 17楼 mathe.
求 x,使得 $ log10(x!)=n $有更有效的算法,只是这部分代码占用的时间很小,我在之前的代码中没有给出更有效更复杂的代码。
下面贴出代码:
函数 faclogEquation(double f) 返回 方程 $log10(x!)=f $ 的解- #define PI 3.1415926535897932384626433832795
- #define LOG10 2.3025850929940456840179914546844
- #define LOGS2PI 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[mid]<f)
- mid++;
- break;
- }
- if ( f>=logfac[mid] )
- {
- low=mid;
- }
- else
- {
- high=mid;
- }
- }
- return mid;
- }
-
- double getLogfac(DWORD n)
- {
- if (n<=128)
- return logfac[n];
- 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[128])
- 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[128])
- return searchInLogFacTab1(f);
-
- i=7;
- while ( logfac_tab[i].logfac<f)
- i++;
- low= logfac_tab[i-1].n;
- high=logfac_tab[i].n;
- return faclogEquation(f,low,high);
- }
复制代码 |
|