unvisibleman

Derivatives: tables and graphs

Mar 1st, 2015
275
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 5.65 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <math.h>
  4.  
  5. #define DO 1
  6. #define NOT 0
  7. // диапазон интегрирования
  8. #define FROM 0
  9. #define TO 1
  10. // настройки графика, отражающие масштаб по осям
  11. #define Xscale 0.02
  12. #define Yscale 0.02
  13.  
  14. float f(float x) { return x*x*cos(x); }
  15.  
  16. int cases; // количество строк, при вычислении с шагом h
  17. float M0, M1, M2; // максимальные по модулю величины для производных соответствующих порядков
  18.  
  19. /* график табличной функции table[], гор. - table[0], верт table[colomn]*/
  20. void draw(float *xarray, float *array, float Xstart, float Xend, float Ystart, float Yend){
  21.     char **graph;
  22.     int i, j;
  23.  
  24.     const int Xsize=(Xend-Xstart)/Xscale+1; //вычисление размера графика
  25.     const int Ysize=(Yend-Ystart)/Yscale+1; // плюс два символа: на концец строки и рамки
  26.  
  27.     /* Выделяем память, заполняем поле пробелами и добавляем рамки */
  28.     graph = malloc(sizeof(char*)*Ysize);
  29.     for(i=0; i<Ysize; i++){
  30.         char filler;
  31.         graph[i] = malloc(sizeof(char)*Xsize);
  32.             graph[i][Xsize] = 0; //помещаем в конец строки нулевой символ
  33.             if(i) // если строка не последняя
  34.                 filler = ' '; // то просто заполняем поле
  35.             else
  36.                 filler = '-'; //то рисуем горизонтальную линию
  37.             graph[i][0]='|';
  38.             for(j=1; j<Xsize; j++)
  39.                 graph[i][j]=filler; //заполняем пробелами пустые места;
  40.     }
  41.     /* отмечаем значения функций */
  42.     // graph[строка - значение функции][столбец - аргумент]
  43.     for(i=0; i<cases; i++)
  44.         graph[ (int)(array[i]/Yscale) ][ (int)(xarray[i]/Xscale) ]='*'; // точка значения
  45.     /* выводим график и сразу же освобождаем память */
  46.     for(i=Ysize-1; i>=0; i--){
  47.         printf("%.3f %s\n", i*Yscale, graph[i]);
  48.         free(graph[i]);
  49.     }
  50.     free(graph);
  51.     // вывести масштаб по горизонтали
  52.     printf("      %d", FROM);
  53.     for(i=1; i<Xsize-1; i++)
  54.         printf(" ");
  55.     printf("%d\n", TO);
  56. }
  57.  
  58. /* h - шаг вычисления значений, int - режим работы (0 - без вывода таблицы) */
  59. float derivative(float h, int mode){
  60.     float *x, *y, *yL, *yR, *yC, *y2;
  61.    
  62.     if(mode)
  63.         printf("x \t f(x) \t f'L(x) \t f'R(x) \t f'C(x) \t f''C(x)\n");
  64.     cases = (TO-FROM)/h;
  65.     int i;
  66.     float x_;
  67.     // значения
  68.         x = malloc(sizeof(float)*cases);
  69.         y = malloc(sizeof(float)*cases);
  70.         yL = malloc(sizeof(float)*cases);
  71.         yR = malloc(sizeof(float)*cases);
  72.         yC = malloc(sizeof(float)*cases);
  73.         y2 = malloc(sizeof(float)*cases);
  74.     for(i=0, x_=FROM; i<=cases; x_+=h, i++){
  75.         y[i] = f( x[i] = x_ ); // значение аргумента и функции
  76.         if(y[i] > M0)
  77.             M0 = y[i]; // выбираем максимальное значение функции
  78.     }
  79.     /* значения первой и второй производных */
  80.     if(mode)
  81.             printf("%.3f \t %.3f \t NaN    \t %.4f \t NaN    \t NaN\n",
  82.                     x[0],   y[0],             yR[0]=(y[1]-y[0])/h);
  83.     for(i=1; i<cases; i++){
  84.         /* знач. первой производной (левая аппрокс.) */
  85.         yL[i] = (y[i]-y[i-1])/h;
  86.         /* знач. первой производной (правая аппрокс.) */
  87.         yR[i] = (y[i+1]-y[i])/h;
  88.         /* знач. первой производной (центральная аппрокс.) */
  89.         yC[i] = (y[i+1]-y[i-1])/(2*h);
  90.         if(yC[i] > M1)
  91.             M1 = yC[i]; // выбираем максимальное значение M1
  92.         /* знач. второй производной */
  93.         y2[i] = (y[i-1]-2*y[i]+y[i+1])/(h*h);
  94.         if(y2[i] > M2)
  95.             M2 = y2[i]; // выбираем максимальное значение M2
  96.         /* вывод таблицы */
  97.         if(mode)
  98.             printf("%.3f \t %.3f \t %.4f \t %.4f \t %.4f \t %.3f\n",
  99.                 x[i], y[i], yL[i], yR[i], yC[i], y2[i]);
  100.     }
  101.     if(mode){
  102.         /* График функции и график первой производной */
  103.         printf("График функции: ордината - f(x), абсцисса - x\n");
  104.         draw(x, y, FROM, TO, 0, M0);
  105.         printf("График первой производной функции: ордината - f'(x), абсцисса - x\n");
  106.         draw(x, yL, FROM, TO, 0, M1);
  107.     }
  108.     return yC[1];
  109. }
  110.  
  111. short int Runge(double eps, float h){
  112.     // считаем производные
  113.     float val1 = derivative(h, NOT);
  114.     float val2 = derivative(h/2, NOT);
  115.     // если разница мала то 1, иначе 0
  116.     if( fabsf(val1 - val2) < eps ){
  117.         printf("Шаг %f подошёл\n", h);
  118.         return 1;
  119.     }else{
  120.         return 0;
  121.     }
  122. }
  123.  
  124. int main(){
  125.     float h, eps;
  126.     srand(time(NULL)); //let's be random
  127.    
  128.     printf("Введите начальный шаг: ");
  129.     scanf("%f", &h);
  130.     printf("Точность для принципа Рунге: ");
  131.     scanf("%f", &eps);
  132.    
  133.     /* определение максимальных значений */
  134.     printf("Определение максимальных значений...\n");
  135.     float temp = derivative(h, 0);
  136.     printf("Максимальные значения определены: M1=%f, M2=%f\n", M1, M2);
  137.     /* запуск метода Рунге */
  138.         printf("Запуск метода Рунге.\n");
  139.     while( Runge(eps, h) == 0 ) h/=2;
  140.     // рассчитываем производные в этой точке и строим графики
  141.     derivative(h, DO);
  142.    
  143.     return 0;
  144. }
Advertisement
Add Comment
Please, Sign In to add comment