LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
123
返回列表 发新帖
楼主: pupilzeng

求定积分有什么好的算法吗?

[复制链接]
 楼主| 发表于 2003-10-29 19:16:21 | 显示全部楼层

谢谢lordbyorn

不过你提供的函数还是没法满足我所要的精度。
这时由c语言原始数据类型精度限制的。
我使用了gmp库,可以达到很高的精度了,起码小数点后几十位是没问题的。而且很容易扩充成更高精度的。

  1. #include<stdio.h>
  2. #include<gmp.h>
  3. #include<stdlib.h>

  4. #define PREC 328

  5. void normal_cdf(mpf_t, const mpf_t, unsigned long int);

  6. int
  7. main(int argc, char * argv[])
  8. {
  9.         double var;
  10.         unsigned long int eff;
  11.         var = atof(argv[1]);
  12.         eff = atof(argv[2]);
  13.         mpf_t x, result;
  14.         mpf_init(result);
  15.         mpf_init_set_d(x, var);
  16.         normal_cdf(result, x, eff);
  17.         char format[50];
  18.         sprintf(format, "norma_cdf(%%f) = %%.%dFe\n", eff);
  19.         gmp_printf(format, var, result);
  20.         mpf_clear(result);       
  21.         mpf_clear(x);
  22.         return 0;
  23. }
  24. void
  25. normal_cdf(mpf_t result,const mpf_t x, unsigned long int eff)
  26. {       
  27.         mpz_t n;
  28.         mpf_t  a, error;
  29.         mpq_t q;
  30.         mpz_init(n);
  31.         mpf_init(a);
  32.         mpq_init(q);
  33.         mpf_init(error);
  34.         mpf_set_prec(a, PREC);
  35.         mpf_set_prec(result, PREC);
  36.         mpf_set_prec(error, PREC);
  37.        
  38.         mpf_set_str(a, "0.3989422804014326779399460599343818684758586311649346576659258296706579258993018385012523339073069364", 10);
  39. //                printf("error\n");
  40. //        gmp_printf("a = %.100Ff\n", a);
  41. //        gmp_printf("error = %40Ff\n", error);
  42. //        gmp_printf("x =%20Ff \n", x);
  43.         mpf_set_d(result, 0.5);
  44. //        gmp_printf("result =%20Ff \n", result);
  45.         mpf_mul(a, a, x);
  46. //        gmp_printf("a = %.100Ff\n", a);
  47.         mpf_t dist, temp;
  48.         mpf_init(dist);
  49.         mpf_init(temp);
  50.         mpf_set_prec(dist, PREC);
  51.         mpf_set_prec(temp, PREC);
  52.         mpz_t num, den;
  53.         mpz_init(num);
  54.         mpz_init(den);
  55.         mpf_set_d(error, 10);
  56. //        gmp_printf("error =%20Ff \n", error);
  57.         mpf_pow_ui(error, error, eff + 1);
  58. //        gmp_printf("error =%20Ff \n", error);
  59.         mpf_ui_div(error, 1, error);
  60. //        gmp_printf("error =%20Ff \n", error);
  61.         do
  62.         {
  63. //                gmp_printf("\nthe %Zd-th loop \n", n);
  64.                 mpf_add(result, result, a);
  65. //                gmp_printf("result =%20Ff \n", result);
  66.                 mpz_add_ui(n, n, 1);
  67.                 mpz_mul_ui(num, n, 2);
  68.                 mpz_sub_ui(num, num, 1);
  69. //                gmp_printf("num =%Zd \n", num);
  70.                 mpz_add_ui(den, num, 2);
  71.                 mpz_mul(den, den, n);
  72.                 mpz_mul_ui(den, den, 2);
  73. //                gmp_printf("den =%Zd \n", den);
  74.                 mpq_set_num(q, num);
  75.                 mpq_set_den(q, den);
  76.                 mpf_set_q(temp, q);
  77. //                gmp_printf("temp = %20Ff\n", temp);
  78.                 mpf_mul(temp, temp, x);
  79.                 mpf_mul(temp, temp, x);
  80.                 mpf_neg(temp, temp);
  81.                 mpf_mul(a, a, temp);
  82. //                gmp_printf("a = %.20Ff\n", a);
  83.                 mpf_set(dist, a);
  84. //                gmp_printf("dist =%20Ff \n", dist);
  85.                 mpf_div(dist, dist, result);
  86.                 mpf_abs(dist, dist);
  87. //                gmp_printf("dist =%.70Ff \n", dist);
  88.         }while(mpf_cmp(dist, error) > 0);
  89. //        gmp_printf("phi_cdf(%f) = %.4Fe \n", var, result);
  90.         mpf_clear(a);
  91.         mpq_clear(q);
  92.         mpf_clear(dist);
  93.         mpf_clear(temp);
  94.         mpf_clear(error);
  95.         mpz_clear(n);
  96.         mpz_clear(num);
  97.         mpz_clear(den);
  98. }
复制代码

编译时需要libgmp3-dev库,使用gcc -lgmp -o normal_cdf normal_cdf.c编译。
运行方法:normal_cdf var prec
第一个参数:要求概率函数的自变量。
第二个参数:结果的精确度,即小数点后面的位数。

这个级数的收敛速度不错,是你自己推导出来的吗?
佩服ing
发表于 2003-10-29 20:22:53 | 显示全部楼层
不错
发表于 2003-10-29 23:30:10 | 显示全部楼层
Compare to your code, my code looks like pseudocode.
这个级数的收敛速度不错,是你自己推导出来的吗?

Not very hard. :p
 楼主| 发表于 2003-10-29 23:37:19 | 显示全部楼层
最初由 Sandy 发表
f:=dy/dx不够精确,I like some cool methods

其实要提高精度单从算法上来说并不难,主要是受到c语言本身的数据精度影响。
所以要特别高的精度的话,还是要利用任意精度的数学库。
发表于 2006-5-24 09:33:13 | 显示全部楼层
浮点数运算密集的话可以考虑用 mpfr 数学库,基于gmp的,不过精度控制和舍入误差比较合理。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

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