====== 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
#include
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
#include
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
#include // 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
#include // 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.