====== 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.