[WikiDyd] [TitleIndex] [WordIndex

Języki i metodyka programowania

Przykłady z wykładów w semestrze jesiennym 2011

Wykład III, 18 października 2011

Pisaliśmy program wyznaczający współczynniki regresji liniowej dla danego zbioru punktów {x_i,y_i}:

   1 #include <stdio.h>
   2 
   3 #define MAXP 4096
   4 
   5 /* Wczytuje dane ze strumienia in do x,y
   6    in - strumien wejsciowy powinien zawierać parzystą liczbę liczb 
   7    x[i] <- pierwsza liczba i-tej pary
   8    y[i] <- druga liczba
   9 
  10    Uwaga: nie sprawdza, czy x,y nie zostaną przepłnione
  11 */
  12 int wczytaj_dane( FILE *, double x[], double y[] );
  13 
  14 /* Wyznacza współczynniki a i b takie, aby 
  15    sum( a*x[i]+b -y[i] )^2, i=0,..,n-1
  16    była minimalna
  17 */
  18 void reg_lin( double x[], double y[], int n, double* a, double *b );
  19 
  20 /*
  21 Wyznacza sum( a*x[i]+b -y[i])^2, i=0,..,n-1
  22 */
  23 double blad_reg_lin( double x[], double y[], int n, double a, double b );
  24 
  25 int main( int argc, char *argv[] ) {
  26         double x[MAXP];
  27         double y[MAXP];
  28         int n;
  29         FILE *in= argc > 1 ? fopen( argv[1], "r" ) : stdin;
  30         double a,b;
  31 
  32         n= wczytaj_dane( in, x, y );
  33 
  34         if( n == -1 ) {
  35                 printf( "%s: nie moge otworzyc pliku %s\n", argv[0], argv[1] );
  36                 return 1;
  37         } else if( n == -2 ) {
  38                 printf( "%s: strumien wejsciowy nie zawiera par liczb\n", argv[0] );
  39                 return 2;
  40   }
  41 
  42         reg_lin( x, y, n, &a, &b );
  43 
  44         printf( "a=%g\n"
  45           "b=%g\n", a, b );
  46 
  47         printf( "blad=%g\n", blad_reg_lin( x, y, n, a, b ) );
  48 
  49         printf( "n=%d\n", n );
  50 
  51         return 0;
  52 }
  53 
  54 int wczytaj_dane( FILE *in, double x[], double y[] ) {
  55         int i=0;
  56         int c;
  57 
  58   if( in == NULL )
  59                 return -1;      
  60 
  61         while( (c= fscanf( in, "%lf %lf", &x[i], &y[i] )) == 2 )
  62                 i++;
  63 
  64         if( c != 1 && feof( in ) )
  65                 return i;
  66         else
  67                 return -2;
  68 }
  69 
  70 void reg_lin( double x[], double y[], int n, double* a, double *b ) {  
  71         double sx= 0;
  72         double sxx= 0;
  73   double sxy= 0;
  74   double sy= 0;
  75         double del;
  76         int i;
  77 
  78         *a= *b= 0;
  79 
  80         if( n < 2 )
  81                 return;
  82 
  83         for( i= 0; i < n; i++ ) {
  84                 sx+= x[i];
  85                 sxx+= x[i]*x[i];
  86                 sxy+= x[i]*y[i];
  87                 sy+= y[i];
  88         }
  89 
  90         del = n*sxx-sx*sx;
  91   
  92         *a= (n*sxy-sx*sy)/del;
  93         *b= (sxx*sy-sx*sxy)/del;
  94 }
  95 
  96 double blad_reg_lin( double x[], double y[], int n, double a, double b )
  97 {
  98         double e= 0;
  99 
 100   for( n--; n >= 0; n-- )
 101                 e += (a*x[n]+b-y[n])*(a*x[n]+b-y[n]);
 102 
 103         return e;
 104         
 105 }

Potem zaczęliśmy zastanawiać się nad tym, że dobrze byłoby wskazać w programie, że tablice x i y są powiązane. Aby zilustrowac problem rozpoczęliśmy od napisania programu, który sprawdza, czy wartości w tablicy x są różne:

   1 #include <stdio.h>
   2 #include <math.h>
   3 #include "wczytajdane.h"
   4 
   5 #define MAXP 4096
   6 
   7 int sprawdz_x( double x[], int n, double eps ) {
   8         int i,j;
   9         for( i= 0; i < n-1; i++ )
  10                 for( j= i+1; j < n; j++ )
  11                         if( fabs(x[i]-x[j]) < eps )
  12                                 return i;
  13 
  14         return -1;
  15 }
  16 
  17 int main( int argc, char *argv[] ) {
  18         double x[MAXP];
  19         double y[MAXP];
  20         int n;
  21         FILE *in= argc > 1 ? fopen( argv[1], "r" ) : stdin;
  22         double a,b;
  23         int p;
  24 
  25         n= wczytaj_dane( in, x, y );
  26 
  27         if( n == -1 ) {
  28                 printf( "%s: nie moge otworzyc pliku %s\n", argv[0], argv[1] );
  29                 return 1;
  30         } else if( n == -2 ) {
  31                 printf( "%s: strumien wejsciowy nie zawiera par liczb\n", argv[0] );
  32                 return 2;
  33   }
  34 
  35         if( (p=sprawdz_x( x, n, 1e-50 )) >= 0 ) {
  36                 printf( "%s: x[%d]=%g się powtarza\n", argv[0], p, x[p] );
  37         } else {
  38                 printf( "%s: jest dobrze!\n", argv[0] );
  39         }
  40 
  41         return 0;
  42 }

Proszę zwrócić uwagę, że przenieśliśmy f. wczytującą do innego pliku. Stworzyliśmy w tym celu plik zawierający deklarację funkcji (wczytajdane.h):

   1 int wczytaj_dane( FILE *, double x[], double y[] );

i plik zawierający jej definicję (wczytajdane.c):

   1 #include <stdio.h>
   2 
   3 int wczytaj_dane( FILE *in, double x[], double y[] ) {
   4         int i=0;
   5         int c;
   6 
   7   if( in == NULL )
   8                 return -1;      
   9 
  10         while( (c= fscanf( in, "%lf %lf", &x[i], &y[i] )) == 2 )
  11                 i++;
  12 
  13         if( c != 1 && feof( in ) )
  14                 return i;
  15         else
  16                 return -2;
  17 }

Ten drugi plik nie jest na razie do końca poprawny - wrócimy do tego na następnych zajęciach.


2015-09-23 06:44