method.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. #include <math.h>
  5. #include "header.h"
  6. double polyval(double* coeffs, double x, int n) {
  7. double ans = 0;
  8. for (int i = 0;i < n + 1;i++) {
  9. ans += coeffs[i] * pow(x, n - i);
  10. }
  11. return ans;
  12. }
  13. double* polyder(double* coeffs, int n) {
  14. double* der = malloc(sizeof(double) * (n));
  15. for (int i = 0;i < n ;i++) {
  16. der[i] = coeffs[i] * (n - i);
  17. }
  18. return der;
  19. }
  20. double newton_solve(double* coeffs, int n, double a, double b) {
  21. double x_next=b,x_prev = b;
  22. double* der = polyder(coeffs, n);
  23. do{
  24. x_prev = x_next;
  25. x_next = x_prev - polyval(coeffs, x_prev, n) / polyval(der, x_prev, n - 1);
  26. } while (fabs(x_next - x_prev) >= 10e-10);
  27. free(der);
  28. return x_next;
  29. }
  30. double* solve_poly(double* coeffs, int n,double a,double b) {
  31. double* xx = calloc(n,sizeof(double));
  32. int c = 0;
  33. double x1 = a, x2 = a;
  34. while (x1 < b) {
  35. while (x2 < x1) {
  36. if (polyval(coeffs, x1, n) * polyval(coeffs, x2, n) < 0) {
  37. xx[c] = newton_solve(coeffs, n, x2, x1);
  38. c++;
  39. x1 = x2;
  40. x2 += (b - a) / 10000;
  41. break;
  42. }
  43. x2 += (b - a) / 10000;
  44. }
  45. x1 += (b - a) / 10000;
  46. }
  47. return xx;
  48. }
  49. double** table_xx() {
  50. double** ret = malloc(sizeof(double*) * 4);
  51. for (int n = 2;n <= 5;n++) {
  52. double* coeffs = malloc(sizeof(double) * (n + 1));
  53. double* sk = malloc(sizeof(double) * (n + 1));
  54. if (coeffs == NULL || sk == NULL) {
  55. exit(16);
  56. }
  57. coeffs[0] = 1;
  58. double A = 2.0 / n;
  59. for (int i = 1;i < (n + 1);i++) {
  60. sk[i] = (1.0 / (i + 1) - pow(-1, i + 1) / (i + 1)) / A;
  61. coeffs[i] = sk[i];
  62. for (int j = 1;j < i;j++) {
  63. coeffs[i] += coeffs[j] * sk[i - j];
  64. }
  65. coeffs[i] *= -1.0 / i;
  66. }
  67. ret[n-2] = solve_poly(coeffs, n, -1, 1);
  68. free(sk);
  69. free(coeffs);
  70. }
  71. return ret;
  72. }
  73. double chebyshev_method(double(*f)(double), double a1, double b1, int n, double** xx_tab) {
  74. double s = 0, a, b, ans;
  75. a = a1;
  76. b = b1;
  77. double* xx = xx_tab[n - 2];
  78. double A = 2.0 / n;
  79. ans = 0;
  80. for (int k = 0;k < n;k++) {
  81. ans += f((a + b) / 2 + ((b - a) / 2) * xx[k]);
  82. }
  83. s = ((b - a) / 2) * ans * A;
  84. return s;
  85. }
  86. double adaptive_div(double(*f)(double),double** xx_tab,double a,double b,int n,int power, double S_n,double S_n_plus_1,int *N,double* len) {
  87. if (fabs(S_n_plus_1 - S_n) < pow(10,-power)/(*N)) {
  88. return S_n;
  89. }
  90. else {
  91. double S_n_plus_1_r = chebyshev_method(f, a, (a + b) / 2, n+1, xx_tab);
  92. double S_n_r = chebyshev_method(f, a, (a + b) / 2, n, xx_tab);
  93. double S_n_plus_1_l = chebyshev_method(f, (a + b) / 2, b, n+1, xx_tab);
  94. double S_n_l = chebyshev_method(f, (a + b) / 2, b,n, xx_tab);
  95. *N += 1;
  96. if (*len > (b - a) / (*N)) {
  97. *len = (b-a)/(*N);
  98. }
  99. return (adaptive_div(f, xx_tab, a, (a + b) / 2, n, power, S_n_l, S_n_plus_1_l,N,len) + adaptive_div(f, xx_tab, (a + b) / 2, b, n, power, S_n_r, S_n_plus_1_r,N,len));
  100. }
  101. }
  102. double adaptive_div_Richardson(double** xx_tab, double a, double b, double(*f)(double), int n, int power, double S_prev, double S_new, int* N, double* len) {
  103. if (fabs(S_new - S_prev)/(pow(2,n)-1) < pow(10, -power) / ( (*N))) {
  104. return S_new;
  105. }
  106. else {
  107. double S_newl = chebyshev_method(f, a, (a + b) / 2, n + 1, xx_tab);
  108. double S_prevl = chebyshev_method(f, a, (a + b) / 2, n, xx_tab);
  109. double S_newr = chebyshev_method(f, (a + b) / 2, b, n + 1, xx_tab);
  110. double S_prevr = chebyshev_method(f, (a + b) / 2, b, n, xx_tab);
  111. *N += 1;
  112. if (*len > (b - a) / (*N)) {
  113. *len = (b - a) / (*N);
  114. }
  115. return (adaptive_div_Richardson(xx_tab, a, (a + b) / 2, f, n, power, S_prevl, S_newl, N, len) + adaptive_div_Richardson(xx_tab, (a + b) / 2, b, f, n, power, S_prevr, S_newr, N, len));
  116. }
  117. }
  118. double find_approx_integral(double(*f)(double), double a, double b, int n, int power, int* counter,double* length,int richardson) {
  119. int N = 1;
  120. double** xx_table = table_xx(a, b);
  121. double S2;
  122. double len = 10000;
  123. if (richardson) {
  124. S2 = adaptive_div_Richardson(xx_table, a, b, f, n, power, 1000000, 100, &N, &len);
  125. }
  126. else {
  127. S2 = adaptive_div(f,xx_table, a, b, n, power, 1000000, 100, &N, &len);
  128. }
  129. printf("N = %ld, n = %d, S = %.15lf, eps = %e, len=%.16lf\n", N,n, S2, pow(10, -power),len);
  130. *counter = N;
  131. *length = len;
  132. return S2;
  133. }