Dvojrozměrná pole

Obdélníkové pole (matice) o pevném počtu řádků a sloupců.
( V našich příkladech budedeme používat první index pro číslo řádky, druhý index pro číslo sloupce. )

   double a [3] [4];

Při přístupu k prvkům pole musíme použít pro oba indexy samostatné hranaté závorky.
Např. vyzvednutí hodnoty z “rohového” prvku z první řádky (řádky s indexem 0) a prvního sloupce (sloupce s indexem 0)

   v = a[0][0];
   -------------------------------------------------
   |  a[0][0]  |  a[0][1]  |  a[0][2]  |  a[0][3]  |
   -------------------------------------------------
   |  a[1][0]  |  a[1][1]  |  a[1][2]  |  a[1][3]  |
   -------------------------------------------------
   |  a[2][0]  |  a[2][1]  |  a[2][2]  |  a[2][3]  |
   -------------------------------------------------

V paměti jsou řádky uloženy bezprostředně za sebou.

   --------------------------------------------------------------------------------------------------------------------------------------------------
   |  a[0][0]  |  a[0][1]  |  a[0][2]  |  a[0][3]  |  a[1][0]  |  a[1][1]  |  a[1][2]  |  a[1][3]   |  a[2][0]  |  a[2][1]  |  a[2][2]  |  a[2][3]  |
   --------------------------------------------------------------------------------------------------------------------------------------------------

Kombinační čísla

#include <iostream>
#include <iomanip>
 
using namespace std;
 
const int M = 10;
int p [M][M];
 
int main ()
{
    for (int i = 0; i < M; i++)
    {
        for (int j = 0; j < M; j++)
        {
           p[i][j] = 0;
        }
    }
 
    p[0][0] = 1;
    for (int n = 1; n < M; n++)
    {
        p[n][0] = 1;
        p[n][n] = 1;
        for (int k = 1; k < n; k++)
        {
            p[n][k] = p[n-1][k-1] + p[n-1][k];
        }
    }
 
 
   for (int n = 0; n < M; n++)
   {
       for (int k = 0; k <= n; k++)
       {
           cout << p[n][k] << " ";
       }
       cout << endl;
   }
 
  return 0;
}

Sčítání a násobení matic

#include <iostream>
#include <cassert>
using namespace std;
 
const int R = 8;
const int S = 8;
 
// typedef long long T;
typedef double T;
 
void add(T v[R][S], T a[R][S], T b[R][S]) // v = a + b
{
    for (int i = 0; i < R; i++)
    {
        for (int k = 0; k < S; k++)
        {
            v[i][k] = a[i][k] + b[i][k];
        }
    }
}
 
void dupl (T v[R][S], T a[R][S]) // v = a 
{
    for (int i = 0; i < R; i++)
    {
        for (int k = 0; k < S; k++)
        {
            v[i][k] = a[i][k];
        }
    }
}
 
typedef T Array [R][S];
 
void mul (T v[R][S], T a[R][S], T b[R][S]) // v = a * b
{
    Array aa;
    Array bb;
    dupl (aa, a);
    dupl (bb, b);
    assert (R == S);
 
    for (int i = 0; i < R; i++)
    {
        for (int k = 0; k < S; k++)
        {
            T sum = 0;
            for (int n = 0; n < R; n++)
            {
                sum = sum + aa[i][n] * bb[n][k];
            }
            v[i][k] = sum;
        }
    }
}
 
void one (T v[R][S]) // v = ( 1 )
{
    for (int i = 0; i < R; i++)
    {
        for (int k = 0; k < S; k++)
        {
            if (i == k)
            {
                v[i][k] = 1;
            }
            else
            {
                v[i][k] = 0;
            }
 
            // v[i][k] = (i == k) ? 1 : 0;
        }
    }
}
 
void zero (T v[R][S]) // v = ( 0 )
{
    for (int i = 0; i < R; i++)
    {
        for (int k = 0; k < S; k++)
        {
            v[i][k] = 0;
        }
    }
}
 
void print (T v[R][S]) 
{
    cout << "[" << endl;
    for (int i = 0; i < R; i++)
    {
        cout << "   ( ";
        for (int k = 0; k < S; k++)
        {
            cout << v[i][k];
            if (k < S - 1)
            {
                cout << ", ";
            }
        }
        cout << " )" << endl;
    }
    cout << "]" << endl;
}
 
T x [R][S];
T y [R][S];
T z [R][S];
T w [R][S];
 
int main ()
{
    one (x);
    one (y);
    add (z, x, y); // z = x + y
    mul (z, z, z);
    print (w);
 
    return 0;
}

První pokus o řešení soustavy lineárních rovnic

Budeme “doufat”, že na diagonále nevyjde nula

#include <iostream>
#include <iomanip> // setw, setprecision
 
using namespace std;
 
const int N = 3;
 
double a [N] [N+1] =
{
    { 1, 2, 3, 140 },  // x  + 2y + 3z = 140
    { 4, 4, 0, 120 },  // 4x + 4y      = 120
    { 0, 8, 4, 280 }   //      8y + 4z = 280
};
 
const string name [N] = { "x", "y", "z" };
 
void print ()
{
    cout << setprecision (5); // pocet desetinnych mist, http://www.cplusplus.com/reference/iomanip/setprecision
 
    for (int r = 0; r < N; r++)
    {
        for (int k = 0; k < N; k++)
        {
            double v = a[r][k];
            if (k > 0)
            {
               cout << " "; // pokud nejsme na prvnim sloupci, tak pridame mezeru
            }
 
            if (v < 0)
            {
               cout << "-";
            }
            else if (k > 0) // pokud nejsme na prvnim sloupci
            {
               cout << "+";
            }
 
            cout << setw (10); // pocet znaku pro nasledujici cislo, http://www.cplusplus.com/reference/iomanip/setw
            cout << abs (v);
            cout << " " ;
            cout << name [k];
        }
        cout << " = ";
        cout << a [r][N] ;
        cout << endl;
    }
    cout << endl; // jedna prazdna radka
}
 
void div (int r, double c) // vydelit r-tou radku cislem c
{
    for (int k = 0; k <= N; k++) // od nuly do N, tj. vcetne prave strany
    {
        a[r][k] /= c;
    }
}
 
void add (int r, int s, double c) // k r-te radce pricit s-tou radku vynasobenou cislem c
{
    for (int k = 0; k <= N; k++) // od nuly do N, tj. vcetne prave strany
    {
        a[r][k] +=  c * a[s][k];
    }
}
 
 
void solve ()
{
    for (int r = 0; r < N; r++) // pro jednotlive radky
    {
        print (); // pro informaci
 
        div (r, a[r][r]); // na diagonale v a[r][r] dostaneme jednicku
 
        for (int t = 0; t < N; t++)
        {
            if (t != r) // pro ostatni radky
            {
                add (t, r, -a[t][r]); // v i-tem sloupci bude nula
            }
        }
    }
}
 
double answer [N];
 
void copy_result ()
{
    for (int i = 0; i < N; i ++)
    {
        answer [i] = a[i][N];
        cout << name [i] << " = " << answer [i] << endl;
    }
    cout << endl;
}
 
double orig [N] [N+1];
 
void store_original ()
{
   for (int i = 0; i < N; i++)
   {
      for (int k = 0; k < N+1; k++)
      {
         orig [i][k] = a [i][k];
      }
   }
}
 
void check ()
{
    for (int r = 0; r < N; r++)
    {
        double sum = 0;
        for (int k = 0; k < N; k++)
        {
            sum += answer [k] * orig[r][k];
        }
 
        if (sum == orig[r][N])
        {
            cout << sum << " == " << orig[r][N] << " O.K." << endl;
        }
        else
        {
            cout << sum << " != " << orig[r][N] << " BAD!" << endl;
        }
    }
    cout << endl;
}
 
int main()
{
    store_original ();
    solve ();
    print ();
    copy_result ();
    check ();
    return 0;
}
         1 x +         2 y +         3 z = 140
         4 x +         4 y +         0 z = 120
         0 x +         8 y +         4 z = 280
 
         1 x +         2 y +         3 z = 140
         0 x -         4 y -        12 z = -440
         0 x +         8 y +         4 z = 280
 
         1 x +         0 y -         3 z = -80
         0 x +         1 y +         3 z = 110
         0 x +         0 y -        20 z = -600
 
         1 x +         0 y +         0 z = 10
         0 x +         1 y +         0 z = 20
         0 x +         0 y +         1 z = 30
 
x = 10
y = 20
z = 30
 
140 == 140 O.K.
120 == 120 O.K.
280 == 280 O.K

Případně prohodíme řádky

#include <iostream>
#include <iomanip> // setw, setprecision
 
using namespace std;
 
const int N = 3;
 
#if 0
double a [N] [N+1] =
{
    { 1, 2, 3, 140 },  // x  + 2y + 3z = 140
    { 4, 4, 0, 120 },  // 4x + 4y      = 120
    { 0, 8, 4, 280 }   //      8y + 4z = 280
};
#endif
 
#if 0
double a [N] [N+1] =
{
    { 1, 2, 3, 1},
    { 1, 5, 0, 2 },
    { 0, 2, 1, 3 },
};
#endif
 
#if 0
double a [N] [N+1] =
{
    { 1, 2, 3, 140 },
    { 1, 2, 0,  50 },
    { 0, 2, 1,  70 },
};
#endif
 
#if 1
double a [N] [N+1] =
{
   { 2,  4,  4,  42 },
   { 1,  2,  7,  46 },
   { 2,  2,  0,  14 },
};
#endif
 
#if 0
double a [N] [N+1] =
{
   { 2,  4,  4,  42 },
   { 1,  2,  7,  46 },
   { 2,  4,  2,  14 },
};
#endif
 
const string name [N] = { "x", "y", "z" };
 
void print ()
{
    cout << setprecision (5); // pocet desetinnych mist, http://www.cplusplus.com/reference/iomanip/setprecision
 
    for (int r = 0; r < N; r++)
    {
        for (int k = 0; k < N; k++)
        {
            double v = a[r][k];
            if (k > 0)
            {
               cout << " "; // pokud nejsme na prvnim sloupci, tak pridame mezeru
            }
 
            if (v < 0)
            {
               cout << "-";
            }
            else if (k > 0) // pokud nejsme na prvnim sloupci
            {
               cout << "+";
            }
 
            cout << setw (10); // pocet znaku pro nasledujici cislo, http://www.cplusplus.com/reference/iomanip/setw
            cout << abs (v);
            cout << " " ;
            cout << name [k];
        }
        cout << " = ";
        cout << a [r][N] ;
        cout << endl;
    }
    cout << endl; // jedna prazdna radka
}
 
void div (int r, double c) // vydelit r-tou radku cislem c
{
    for (int k = 0; k <= N; k++) // od nuly do N, tj. vcetne prave strany
    {
        a[r][k] /= c;
    }
}
 
void add (int r, int s, double c) // k r-te radce pricit s-tou radku vynasobenou cislem c
{
    for (int k = 0; k <= N; k++) // od nuly do N, tj. vcetne prave strany
    {
        a[r][k] +=  c * a[s][k];
    }
}
 
void error (string s)
{
    // cerr << s << endl;
    // exit (0);
 
    throw runtime_error (s);
}
 
const double eps = 1e-9;
 
void prohod (int start)
{
    // hledame nejvetsi cislo ( v absolutni hodnote )
    // ve sloupci start
    // pocinaje na radce start+1
 
    double nej = 0; // nejvetsi hodnota ( v absolutni hodnote )
    int inx = -1; // nejvetsi hodnota byla na radku inx
 
    for (int r = start + 1; r < N; r++) // pro radky "pod" radkou start
    {
        if (abs (a[r][start]) > nej)
        {
            nej = abs (a[r][start]); // zapamatovat hodnotu
            inx = r; // zapamatovat index
        }
    }
 
    if (abs(nej) < eps)
    {
       error ("Same nuly");
    }
    else
    {
        cout << "prohazuji radky " << start << " a " << inx << endl;
        // prohodit radky s indexy start a inx
        for (int k = 0; k <= N; k++)
        {
            double tmp = a[start][k];
            a[start][k] = a[inx][k];
            a[inx][k] = tmp;
        }
    }
}
 
void solve ()
{
    for (int r = 0; r < N; r++) // pro jednotlive radky
    {
        print (); // pro informaci
 
 
        if (abs (a[r][r]) < eps)
        {
            prohod (r);
            print ();
        }
 
        div (r, a[r][r]); // na diagonale v a[r][r] dostaneme jednicku
 
        for (int t = 0; t < N; t++)
        {
            if (t != r) // pro ostatni radky
            {
                add (t, r, -a[t][r]); // v i-tem sloupci bude nula
            }
        }
    }
}
 
// double answer [N] = { 10, 20, 30 };
double answer [N];
 
void copy_result ()
{
    for (int i = 0; i < N; i ++)
    {
        answer [i] = a[i][N];
        cout << name [i] << " = " << answer [i] << endl;
    }
    cout << endl;
}
 
double orig [N] [N+1];
 
void store_original ()
{
   for (int i = 0; i < N; i++)
   {
      for (int k = 0; k < N+1; k++)
      {
         orig [i][k] = a [i][k];
      }
   }
}
 
 
void check ()
{
    for (int r = 0; r < N; r++)
    {
        double sum = 0;
        for (int k = 0; k < N; k++)
        {
            sum += answer [k] * orig[r][k];
        }
 
        if (abs (sum - orig[r][N]) < eps)
        {
            cout << sum << " == " << orig[r][N] << " O.K." << endl;
        }
        else
        {
            cout << sum << " != " << orig[r][N] << " BAD!" << endl;
        }
    }
    cout << endl;
}
 
int main()
{
    try
    {
       store_original ();
       solve ();
       print ();
       copy_result ();
       check ();
    }
    catch (exception & e)
    {
        cerr << "Neco se nepovedlo: " << e.what() << endl;
    }
 
    return 0;
}
         2 x +         4 y +         4 z = 42
         1 x +         2 y +         7 z = 46
         2 x +         2 y +         0 z = 14

         1 x +         2 y +         2 z = 21
         0 x +         0 y +         5 z = 25
         0 x -         2 y -         4 z = -28

prohazuji radky 1 a 2
         1 x +         2 y +         2 z = 21
         0 x -         2 y -         4 z = -28
         0 x +         0 y +         5 z = 25

         1 x +         0 y -         2 z = -7
         0 x +         1 y +         2 z = 14
         0 x +         0 y +         5 z = 25

         1 x +         0 y +         0 z = 3
         0 x +         1 y +         0 z = 4
         0 x +         0 y +         1 z = 5

x = 3
y = 4
z = 5

42 == 42 O.K.
46 == 46 O.K.
14 == 14 O.K.
 
zpro/matricies.txt · Last modified: 2020/11/09 23:15 by 88.103.111.44
 
Recent changes RSS feed Creative Commons License Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki