- 注册时间
- 2008-2-6
- 最后登录
- 1970-1-1
- 威望
- 星
- 金币
- 枚
- 贡献
- 分
- 经验
- 点
- 鲜花
- 朵
- 魅力
- 点
- 上传
- 次
- 下载
- 次
- 积分
- 51573
- 在线时间
- 小时
|
发表于 2008-12-17 09:56:24
|
显示全部楼层
#include
#include
#include
#include
#define DefaultBitLength 128
mpfr_t ln10, A;
//=1/2ln(2π)+(n+1/2)ln(n)-n+1/12n
//n > 10^8 误差<1/360Z^3 = 10^(-26)
long double stirling(double n)
{
mpfr_t a, b, c, s;
long double r;
mpfr_init2(a, DefaultBitLength);
mpfr_init2(b, DefaultBitLength);
mpfr_set_d(a, n, GMP_RNDD); //a=n
mpfr_init2(c, DefaultBitLength);
mpfr_set_d(b, 12.0, GMP_RNDD); //b=12
mpfr_set_d(c, 1.0, GMP_RNDD); //c=1
mpfr_init2(s, DefaultBitLength);
mpfr_div(b, c, b, GMP_RNDD); // b = c / b = 1/12
mpfr_div(b, b, a, GMP_RNDD); // b = b / a = 1/12n
mpfr_sub(s, b, a, GMP_RNDD); //s = b - a = - n + 1/12n
mpfr_log(c, a, GMP_RNDD); //c = ln(n)
mpfr_set_d(b, 0.5, GMP_RNDD);
mpfr_add(b, a, b, GMP_RNDD);
mpfr_mul(b, b, c, GMP_RNDD); //b = (n + 1/2)ln(n)
mpfr_add(s, s, b, GMP_RNDD); //s = (n + 1/2)ln(n) - n + 1/12n
mpfr_add(s, s, A, GMP_RNDD); //最终结果s=1/2ln(2*pi) + (n + 1/2)ln(n) - n + 1/12n
mpfr_div(s, s, ln10, GMP_RNDD); //转换为log10
mpfr_floor(b, s);
mpfr_sub(s, s, b, GMP_RNDD); //只要小数
r = mpfr_get_ld(s, GMP_RNDD);
mpfr_clear(a);
mpfr_clear(b);
mpfr_clear(c);
mpfr_clear(s);
return r;
}
int main(void)
{
double a, b, low, hi, lf, t;
double start;
int find = 0;
long i = 0, j = 0;
mpfr_init2(ln10, DefaultBitLength);
mpfr_init2(A, DefaultBitLength);
mpfr_set_d(ln10, 10.0, GMP_RNDD);
mpfr_log(ln10, ln10, GMP_RNDD);
mpfr_const_pi(A, GMP_RNDD);
mpfr_mul_ui(A, A, 2, GMP_RNDD);
mpfr_log(A, A, GMP_RNDD);
mpfr_div_ui(A, A, 2, GMP_RNDD);
printf("请输入起始搜索数字:");
scanf("%lf", &start);
printf("请输入上界: ");
scanf("%lf", &hi);
printf("请输入下界: ");
scanf("%lf", &low);
hi = log10(hi);
low = log10(low);
printf("起始位置:%.0f\n当前界限[%.15f, %.15f]\n", start, low, hi);
a = start;
b = 1.0;
while (a >= 10.0)
{
a /= 10.0;
b /= 10.0;
}
lf = stirling(start);
printf("a: %.15f\nb: %.15f\nlf: %.15f\n", a, b, lf);
while (1)
{
a += b;
start += 1.0;
if (a >= 10.0)
{
a /= 10.0;
b /= 10.0;
}
i ++;
lf += log10(a);
if (lf >= 1.0)
lf -= 1.0;
// printf("[%.0f, %.15f] ", start, lf);
if ((lf >= low) && (lf < hi))
{
find = 1;
break;
}
if (i >= 100)
{
lf = stirling(start);
i = 0;
j ++;
if (j >= 100000)
{
j = 0;
printf(".");
}
}
}
if (find)
{
printf("\n当前界限下的阶乘%.0f!, 对应的对数%.15f", start, lf);
}
mpfr_clear(ln10);
mpfr_clear(A);
return 1;
}
===========================
终于搞定
顺便说下
16#公式是错误的,害死我了
因为偷懒没去找,照抄的
应该是(z+1/2)
===========================
大概每4秒搜索10^8个数据 |
|