It is necessary to calculate the condition number of the matrix by definition and give a lower estimate for this number (that is, an experimental estimate).

The condition number by definition: condA = || A ^ (- 1) || * || A ||. The fact is that before this task, the program implemented the Gauss method for solving the SLAE and the qr-decomposition method. To reverse the matrix (and a 4x4 matrix is ​​given), then I simply solve four equations, where the right side is first (1,0,0,0), (0,1,0,0), (0,0,1,0) , (0,0,0,1). I get the inverse matrix, multiply by the original and get the unit. Everything would be fine, but we picked up a matrix in which it is with the type of "float" that the multiplication is not single. With the type of "double" everything is good, but it is with "float" - nonsense.


The matrix itself (also in the readable file):

0.2910 1.8100 9.3110 9.1100 4.2280 1.4500 8.5790 44.1950 42.9950 20.4290 -0.2900 -1.7980 -9.2500 -9.0500 -4.2080 0.0000 0.0820 0.4100 0.4500 0.1220 

By multiplying the original matrix (see above) and the inverse, it turns out that the matrix is ​​not exactly the same (in some places the numbers in the spirit of 0.06, etc.) emerge. Once again, this happens only with the type "float". For the code, I ask you not to scold too much, I know that it is heavily cluttered.

 #include <iostream> #include <iomanip> #include <cmath> #include <fstream> #include <float.h> using namespace std; typedef float tdouble; const tdouble eps = 1e-16; //ΠΏΡ€ΠΈ 1e-8 DATA9 Π½Π΅ Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ const unsigned n = 4; void product(tdouble**, tdouble*, tdouble*); void product(tdouble**, tdouble**, tdouble**); void output(tdouble**, tdouble*); void output(tdouble*); void output(tdouble **); void changing(tdouble**, tdouble*, int, int); bool gausss(tdouble**, tdouble*); void qr(tdouble**, tdouble*, tdouble**); void qr(tdouble**, tdouble*, tdouble*, tdouble*, tdouble*, tdouble**); void reverse(tdouble**, tdouble*, tdouble*); void spherical(tdouble*, tdouble*)ΠΆ tdouble octahedron(tdouble*); tdouble octahedron(tdouble*, tdouble*); tdouble cubic(tdouble*, tdouble*); tdouble cubic(tdouble *); tdouble cubic_matrix(tdouble **); tdouble octah_matrix(tdouble **); int main() { setlocale(LC_ALL, "Russian"); tdouble **mtx, **mtxun, *vect, *vectun; mtx = new tdouble *[n]; //массив ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»Π΅ΠΉ mtxun = new tdouble *[n]; //нСизмСняСмая ΠΌΠ°Ρ‚Ρ€ΠΈΡ†Π° vect = new tdouble[n]; vectun = new tdouble[n]; ifstream filemat; filemat.open("U:\\FS13\\FS2-x3\\Melikhov\\Metody_vych\\LLaba1 \\DATA9.txt"); for (int i = 0; i < n; i++) { mtxun[i] = new tdouble[n]; mtx[i] = new tdouble[n]; for (int j = 0; j < n + 1; j++) { filemat >> (j == 4 ? vect[i] : mtx[i][j]); //Ссли j == 4 ? vectun[i] = vect[i] : mtxun[i][j] = mtx[i][j]; } } filemat.close(); cout << "\t\tΠ’Ρ‹Π²ΠΎΠ΄ исходной ΠΌΠ°Ρ‚Ρ€ΠΈΡ†Ρ‹ ΠΈ Π²Π΅ΠΊΡ‚ΠΎΡ€Π° ΠΏΡ€Π°Π²ΠΎΠΉ части" << endl << endl; output(mtx, vect); //Π²Ρ‹Π²ΠΎΠ΄ Π½Π° экран ΠΌΠ°Ρ‚Ρ€ΠΈΡ†Ρ‹ ΠΈ ΠΏΡ€Π°Π²ΠΎΠ³ΠΎ Π²Π΅ΠΊΡ‚ΠΎΡ€ //ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° Π½Π° Π²Ρ‹Ρ€ΠΎΠΆΠ΄Π΅Π½Π½ΠΎΡΡ‚ΡŒ bool h = gausss(mtx, vect); tdouble product_diagonal_elements = mtx[0][0]; //ΠΏΡ€ΠΎΠΈΠ·Π²Π΅Π΄Π΅Π½ΠΈΠ΅ Π΄ΠΈΠ°Π³ΠΎΠ½Π°Π»ΡŒΠ½Ρ‹Ρ… элСмСнтов (для ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ выроТдСнности) for (int i = 1; i < n; i++) product_diagonal_elements *= mtx[i][i]; if (!h || abs(product_diagonal_elements) < eps) //Ссли ΠΌΠΎΠ΄ΡƒΠ»ΡŒ произвСдСния Π΄ΠΈΠ°Π³ΠΎΠ½Π°Π»ΡŒΠ½Ρ‹Ρ… элСмСнтов мСньшС эпсилон, Ρ‚ΠΎ Π²Ρ‹Π²ΠΎΠ΄ сообщСния { cout << "ΠœΠ°Ρ‚Ρ€ΠΈΡ†Π° выроТдСнная. Π”ΠΎ свидания!"; } else //ΠΈΠ½Π°Ρ‡Π΅ { tdouble *sol = new tdouble[n], *check = new tdouble[n]; tdouble *sin1 = new tdouble[n], *sin2 = new tdouble[n], *sin3 = new tdouble[n], *sin4 = new tdouble[n]; //Сдиничная правая Ρ‡Π°ΡΡ‚ΡŒ tdouble *solr1 = new tdouble[n], *solr2 = new tdouble[n], *solr3 = new tdouble[n], *solr4 = new tdouble[n]; //Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅ с Π΅Π΄ΠΈΠ½ΠΈΡ‡Π½ΠΎΠΉ ΠΏΡ€Π°Π²ΠΎΠΉ Ρ‡Π°ΡΡ‚ΡŒΡŽ tdouble *solv1 = new tdouble[n], *solv2 = new tdouble[n], *solv3 = new tdouble[n], *solv4 = new tdouble[n]; //Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅ с Π΅Π΄ΠΈΠ½ΠΈΡ‡Π½ΠΎΠΉ ΠΏΡ€Π°Π²ΠΎΠΉ Ρ‡Π°ΡΡ‚ΡŒΡŽ tdouble **mtxrev = new tdouble*[n]; //обратная ΠΌΠ°Ρ‚Ρ€ΠΈΡ†Π° tdouble nun_cub, nrev_cub, condex_cub; //Π½ΠΎΡ€ΠΌΠ° исходной, Π½ΠΎΡ€ΠΌΠ° ΠΎΠ±Ρ€Π°Ρ‚Π½ΠΎΠΉ, число обусловлСнности tdouble nun_oct, nrev_oct, condex_oct; for (int i = 0; i < n; i++) { (i == 0 ? sin1[i] = 1 : sin1[i] = 0); (i == 1 ? sin2[i] = 1 : sin2[i] = 0); (i == 2 ? sin3[i] = 1 : sin3[i] = 0); (i == 3 ? sin4[i] = 1 : sin4[i] = 0); } //ΠΏΡ€ΠΈΠ²ΠΎΠ΄ΠΈΠΌ ΠΊ ΠΏΠ΅Ρ€Π²ΠΎΠ½Π°Ρ‡Π°Π»ΡŒΠ½ΠΎΠΌΡƒ Π²ΠΈΠ΄Ρƒ mtx ΠΈ vect tdouble **T = new tdouble*[n], **mtxcheck = new tdouble*[n]; //создаСм Π½ΠΎΠ²Ρ‹ΠΉ массив T - Π΅Π΄ΠΈΠ½ΠΈΡ‡Π½ΡƒΡŽ ΠΌΠ°Ρ‚Ρ€ΠΈΡ†Ρƒ. ΠŸΠΎΠ½Π°Π΄ΠΎΠ±ΠΈΡ‚ΡΡ для получСния ΠΌΠ°Ρ‚Ρ€ΠΈΡ†Ρ‹ Q for (int i = 0; i < n; i++) { T[i] = new tdouble[n]; mtxrev[i] = new tdouble[n]; mtxcheck[i] = new tdouble[n]; for (int j = 0; j < n; j++) { T[i][j] = (i == j ? 1 : 0); //Ссли i=j, Ρ‚ΠΎΠ³Π΄Π° присваСм 1, ΠΈΠ½Π°Ρ‡Π΅ - 0 mtx[i][j] = mtxun[i][j]; //Π² mtx записываСм Π½Π΅ΠΈΠ·ΠΌΠ΅Π½Π΅Π½Π½ΡƒΡŽ ΠΌΠ°Ρ‚Ρ€ΠΈΡ†Ρƒ mtxun для восстановлСния ΠΏΠ΅Ρ€Π²ΠΎΠΉ } vect[i] = vectun[i]; //Π°Π½Π°Π»ΠΎΠ³ΠΈΡ‡Π½ΠΎ с Π²Π΅ΠΊΡ‚ΠΎΡ€ΠΎΠΌ } //QR-ΠΌΠ΅Ρ‚ΠΎΠ΄ qr(mtx, vect, sin1, sin2, sin3, sin4, T); ////ВранспонируСм T Π² Q, создаСм массив A tdouble **Q = new tdouble*[n], **A = new tdouble*[n]; for (int i = 0; i < n; i++) { Q[i] = new tdouble[n]; A[i] = new tdouble[n]; for (int j = 0; j < n; j++) Q[i][j] = T[j][i]; } //Находим ΠΎΠ±Ρ€Π°Ρ‚Π½ΡƒΡŽ ΠΌΠ°Ρ‚Ρ€ΠΈΡ†Ρƒ reverse(mtx, sin1, solr1); reverse(mtx, sin2, solr2); reverse(mtx, sin3, solr3); reverse(mtx, sin4, solr4); for (int j = 0; j < n; j++) { for (int i = 0; i < n; i++) { if (j == 0) mtxrev[i][j] = solr1[i]; else if (j == 1) mtxrev[i][j] = solr2[i]; else if (j == 2) mtxrev[i][j] = solr3[i]; else if (j == 3) mtxrev[i][j] = solr4[i]; } } cout << "ΠžΠ±Ρ€Π°Ρ‚Π½Π°Ρ ΠΌΠ°Ρ‚Ρ€ΠΈΡ†Π°" << endl; output(mtxrev); product(mtxun, mtxrev, mtxcheck); cout << "ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ°" << endl; output(mtxcheck); cout << endl << endl << "ΠšΡƒΠ±ΠΈΡ‡Π΅ΡΠΊΠ°Ρ Π½ΠΎΡ€ΠΌΠ°" << endl; nun_cub = cubic_matrix(mtxun); nrev_cub = cubic_matrix(mtxrev); condex_cub = nun_cub * nrev_cub; cout << endl << "Норма исходной ΠΌΠ°Ρ‚Ρ€ΠΈΡ†Ρ‹ = " << nun_cub << endl << "Норма ΠΎΠ±Ρ€Π°Ρ‚Π½ΠΎΠΉ ΠΌΠ°Ρ‚Ρ€ΠΈΡ†Ρ‹ = " << nrev_cub << endl << "ΠŸΡ€ΠΎΠΈΠ·Π²Π΅Π΄Π΅Π½ΠΈΠ΅ Π½ΠΎΡ€ΠΌ = " << condex_cub << endl; cout << endl << endl << "ΠžΠΊΡ‚Π°ΡΠ΄Ρ€ΠΈΡ‡Π΅ΡΠΊΠ°Ρ Π½ΠΎΡ€ΠΌΠ°" << endl; nun_oct = octah_matrix(mtxun); nrev_oct = octah_matrix(mtxrev); condex_oct = nun_oct * nrev_oct; cout << endl << "Норма исходной ΠΌΠ°Ρ‚Ρ€ΠΈΡ†Ρ‹ = " << nun_oct << endl << "Норма ΠΎΠ±Ρ€Π°Ρ‚Π½ΠΎΠΉ ΠΌΠ°Ρ‚Ρ€ΠΈΡ†Ρ‹ = " << nrev_oct << endl << "ΠŸΡ€ΠΎΠΈΠ·Π²Π΅Π΄Π΅Π½ΠΈΠ΅ Π½ΠΎΡ€ΠΌ = " << condex_oct << endl; //ΠžΠ±Ρ€Π°Ρ‚Π½Ρ‹ΠΉ Ρ…ΠΎΠ΄ reverse(mtx, vect, sol); tdouble n_dx, n_db, //Π½ΠΎΡ€ΠΌΡ‹ разностСй dx, db nx_d, nb_d, //Π½ΠΎΡ€ΠΌΡ‹ дСлСния Ρ…, b n_x, n_b; //Π½ΠΎΡ€ΠΌΡ‹ x ΠΈ b tdouble max_div, norm_div; //максимум дСлСния, Π½ΠΎΡ€ΠΌΠ° дСлСния tdouble o_dx, o_db, ox_d, ob_d, o_x, o_b, maxo_div, normo_div; //октаэдричСская n_x = cubic(sol); o_x = octahedron(sol); //cout << endl << "n_x " << n_x << endl; n_b = cubic(vectun); o_b = octahedron(vectun); //cout << endl << "n_b " << n_b << endl; max_div = 0; maxo_div = 0; //ΠŸΡ€ΠΈΠ²ΠΎΠ΄ΠΈΠΌ ΠΊ исходному Π²ΠΈΠ΄Ρƒ vect ΠΈ mtx for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) mtx[i][j] = mtxun[i][j]; vect[i] = vectun[i]; } for (int i = 0; i < n; i++) { vect[i] += 0.01; //Π²ΠΎΠ·ΠΌΡƒΡ‰Π°Π΅ΠΌ i-ΡƒΡŽ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρƒ Π²Π΅ΠΊΡ‚ΠΎΡ€Π° vect //cout << "VECT" << endl; //output(vect); n_db = cubic(vect, vectun); o_db = octahedron(vect, vectun); //cout << endl << "n_db " << n_db << endl; qr(mtx, vect, T); reverse(mtx, vect, solv1); //cout << endl; output(solv1); cout << endl; for (int k = 0; k < n; k++) { for (int j = 0; j < n; j++) mtx[k][j] = mtxun[k][j]; vect[k] = vectun[k]; } n_dx = cubic(solv1, sol); o_dx = octahedron(solv1, sol); //cout << endl << "n_dx " << n_dx << endl; nx_d = n_dx / n_x; ox_d = o_dx / o_x; //cout << endl << "nx_d " << nx_d << endl; nb_d = n_db / n_b; ob_d = o_db / o_b; //cout << endl << "nb_d " << nb_d << endl; norm_div = nx_d / nb_d; normo_div = ox_d / ob_d; //cout << endl << "norm_div " << norm_div << endl; if (max_div < norm_div) max_div = norm_div; if (maxo_div < norm_div) maxo_div = normo_div; } cout << endl << "ΠžΡ†Π΅Π½ΠΊΠ° снизу (кубичСская Π½ΠΎΡ€ΠΌΠ°): " << max_div << endl; cout << endl << "ΠžΡ†Π΅Π½ΠΊΠ° снизу (октаэдричСская Π½ΠΎΡ€ΠΌΠ°): " << maxo_div << endl; delete[] sin1; delete[] sin2; delete[] sin3; delete[] sin4; delete[] check; delete[] sol; for (int i = 0; i < n; i++) { delete[] A[i]; delete[] Q[i]; delete[] T[i]; } delete[] A; delete[] Q; delete[] T; } cin.get(); delete[] vect; delete[] vectun; for (int i = 0; i < n; i++) { delete[] mtx[i]; delete[] mtxun[i]; } delete[] mtx; delete[] mtxun; } void reverse(tdouble **mtx, tdouble *vect, tdouble *sol) { //ΠžΠ±Ρ€Π°Ρ‚Π½Ρ‹ΠΉ Ρ…ΠΎΠ΄/ for (int i = n - 1; i >= 0; i--) { tdouble temp = 0; for (int j = i + 1; j < n; j++) //Ρ†ΠΈΠΊΠ» с ΠΏΠ΅Ρ€Π²ΠΎΠ³ΠΎ Ρ€Π°Π·Π° Π½Π΅ ΠΏΡ€ΠΎΠΉΠ΄Π΅Ρ‚, поэтому пустой массив sol[j] сСбя Π½Π΅ ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠΈΡ‚ сначала, Π° ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠΈΡ‚ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ послС ΠΏΠ΅Ρ€Π²ΠΎΠΉ ΠΈΡ‚Π΅Ρ€Π°Ρ†ΠΈΠΈ внСшнСго Ρ†ΠΈΠΊΠ»Π° temp += mtx[i][j] * sol[j]; sol[i] = (vect[i] - temp) / mtx[i][i]; } } bool gausss(tdouble **mtx, tdouble *vect) { tdouble c; //коэффициСнт ΠΌΠ°ΡΡˆΡ‚Π°Π±ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΡ for (int j = 0; j < n; j++) //двигаСмся ΠΏΠΎ столбцам { tdouble temp = abs(mtx[j][j]); //ΠΈΡ‰Π΅ΠΌ максимум Π² столбцС, запоминая j,j-ΠΉ элСмСнт (ΠΈΡ‰Π΅ΠΌ всСгда Π½Π° Π΄ΠΈΠ°Π³ΠΎΠ½Π°Π»ΠΈ ΠΈ Π½ΠΈΠΆΠ΅) int mem = j; //пСрСмСнная для запоминания Π½ΠΎΠΌΠ΅Ρ€Π° строки, Π³Π΄Π΅ ищСтся максимум for (int i = j + 1; i < n; i++) //ΠΎΡ‚ j+1, ΠΏΠΎΡ‚ΠΎΠΌΡƒ Ρ‡Ρ‚ΠΎ ΠΏΠΎΠ΄ диагональю ΠΈΡ‰Π΅ΠΌ ΠΌΠ°ΠΊΡΠΈΠΌΠ°Π»ΡŒΠ½Ρ‹ΠΉ элСмСнт if (temp < abs(mtx[i][j])) { temp = abs(mtx[i][j]); //Π·Π°ΠΏΠΎΠΌΠΈΠ½Π°Π΅ΠΌ Π½ΠΎΠ²Ρ‹ΠΉ максимум mem = i; //Π·Π°ΠΏΠΎΠΌΠΈΠ½Π°Π΅ΠΌ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΡƒΡŽ строку } if (temp < eps) return false; //Ссли максимум сравним с Π½ΡƒΠ»Π΅ΠΌ, Ρ‚ΠΎ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌ false, Ρ‚ΠΎ Π΅ΡΡ‚ΡŒ дальшС Ρ€Π°Π±ΠΎΡ‚Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ бСссмыслСнна changing(mtx, vect, mem, j); //мСняСм мСстами строки for (int i = j + 1; i < n; i++) //Ρ†ΠΈΠΊΠ» для вычислСния коэффициСнтов ΠΌΠ°ΡΡˆΡ‚Π°Π±ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΡ ΠΈ прСобразования { c = mtx[i][j] / mtx[j][j]; for (int k = j; k < n; k++) mtx[i][k] -= c * mtx[j][k]; //пСрСсчитываСм i-ю строку Π² ΠΌΠ°Ρ‚Ρ€ΠΈΡ†Π΅ (линСйная комбинация)... vect[i] -= c * vect[j]; //... ΠΈ Π² Π²Π΅ΠΊΡ‚ΠΎΡ€Π΅ } } return true; //Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌ истину } void qr(tdouble **mtx, tdouble *vect, tdouble **T) //ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏ: мСняСм мСстами строки Ρ‚Π°ΠΊ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π½Π΅ Π±Ρ‹Π»ΠΎ дСлСния Π½Π° ноль. Π—Π°Ρ‚Π΅ΠΌ вычисляСм коэффициСнты ΠΈ замСняСм строки Π½Π° Π»ΠΈΠ½Π΅ΠΉΠ½Ρ‹Π΅ ΠΊΠΎΠΌΠ±ΠΈΠ½Π°Ρ†ΠΈΠΈ { //QR-ΠΌΠ΅Ρ‚ΠΎΠ΄ for (int k = 0; k < n; k++) //ΠΈΠ΄Π΅ΠΌ ΠΏΠΎ строкС { //int z = k; //Π·Π°ΠΏΠΎΠΌΠΈΠ½Π°Π΅ΠΌ Π½ΠΎΠΌΠ΅Ρ€ строки //while (abs(mtx[z][k]) < eps && z < n) //ΠΏΠΎΠΊΠ° Π½ΡƒΠ»Π΅Π²ΠΎΠΉ элСмСнт, ΡƒΠ²Π΅Π»ΠΈΡ‡ΠΈΠ²Π°Π΅ΠΌ z, Π·Π°ΠΏΠΎΠΌΠΈΠ½Π°ΡŽΡ‰ΡƒΡŽ строку. Π’Π°ΠΊΠΆΠ΅ провСряСтся Π²Ρ‹Ρ…ΠΎΠ΄ Π·Π° ΠΏΡ€Π΅Π΄Π΅Π»Ρ‹ массива. // z++; //if (z != k) // changing(mtx, vect, z, k); tdouble c, s, temp_sqr; //c,s - коэффициСнты, temp_sqr - Π²Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹ΠΉ ΠΊΠΎΡ€Π΅Π½ΡŒ for (int i = k + 1; i < n; i++) //сдвигаСмся Π½Π° строчку Π²Π½ΠΈΠ· ΠΈ считаСм: { //подсчСт коэффициСнтов if (abs(mtx[i][k]) < eps) continue; temp_sqr = sqrt(mtx[k][k] * mtx[k][k] + mtx[i][k] * mtx[i][k]); c = mtx[k][k] / temp_sqr; s = mtx[i][k] / temp_sqr; tdouble temp, tempT; for (int j = 0; j < n; j++)//k { //Π·Π°ΠΌΠ΅Π½Π° Π½Π° Π»ΠΈΠ½Π΅ΠΉΠ½Ρ‹Π΅ ΠΊΠΎΠΌΠ±ΠΈΠ½Π°Ρ†ΠΈΠΈ tempT = T[k][j]; T[k][j] = c * T[k][j] + s * T[i][j]; T[i][j] = -s * tempT + c * T[i][j]; if (j >= k) // Ρ‡Ρ‚ΠΎΠ±Ρ‹ лишний Ρ€Π°Π· Π½Π΅ ΠΏΠ΅Ρ€Π΅ΡΡ‡ΠΈΡ‚Ρ‹Π²Π°Ρ‚ΡŒ Π½ΡƒΠ»ΠΈ { temp = mtx[k][j]; //сохраняСм ΠΏΠ΅Ρ€Π²ΡƒΡŽ строку Π²ΠΎ Π²Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ mtx[k][j] = c * mtx[k][j] + s * mtx[i][j]; //замСняСм k-ю строку Π½Π° Π»ΠΊ с коэффициСнтами c ΠΈ s mtx[i][j] = -s * temp + c * mtx[i][j]; //замСняСм j-ю строку Π½Π° Π»ΠΊ с использованиСм ΠΏΠ΅Ρ€Π²ΠΎΠ½Π°Ρ‡Π°Π»ΡŒΠ½ΠΎΠΉ k-ΠΉ строки } } //Π°Π½Π°Π»ΠΎΠ³ΠΈΡ‡Π½ΠΎ с Π²Π΅ΠΊΡ‚ΠΎΡ€ΠΎΠΌ ΠΏΡ€Π°Π²ΠΎΠΉ части temp = vect[k]; vect[k] = c * vect[k] + s * vect[i]; vect[i] = -s * temp + c * vect[i]; } } } void qr(tdouble **mtx, tdouble *vect, tdouble *sin1, tdouble *sin2, tdouble *sin3, tdouble *sin4, tdouble **T) //ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏ: мСняСм мСстами строки Ρ‚Π°ΠΊ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π½Π΅ Π±Ρ‹Π»ΠΎ дСлСния Π½Π° ноль. Π—Π°Ρ‚Π΅ΠΌ вычисляСм коэффициСнты ΠΈ замСняСм строки Π½Π° Π»ΠΈΠ½Π΅ΠΉΠ½Ρ‹Π΅ ΠΊΠΎΠΌΠ±ΠΈΠ½Π°Ρ†ΠΈΠΈ { //QR-ΠΌΠ΅Ρ‚ΠΎΠ΄ for (int k = 0; k < n; k++) //ΠΈΠ΄Π΅ΠΌ ΠΏΠΎ строкС { //int z = k; //Π·Π°ΠΏΠΎΠΌΠΈΠ½Π°Π΅ΠΌ Π½ΠΎΠΌΠ΅Ρ€ строки //while (abs(mtx[z][k]) < eps && z < n) //ΠΏΠΎΠΊΠ° Π½ΡƒΠ»Π΅Π²ΠΎΠΉ элСмСнт, ΡƒΠ²Π΅Π»ΠΈΡ‡ΠΈΠ²Π°Π΅ΠΌ z, Π·Π°ΠΏΠΎΠΌΠΈΠ½Π°ΡŽΡ‰ΡƒΡŽ строку. Π’Π°ΠΊΠΆΠ΅ провСряСтся Π²Ρ‹Ρ…ΠΎΠ΄ Π·Π° ΠΏΡ€Π΅Π΄Π΅Π»Ρ‹ массива. // z++; //if (z != k) // changing(mtx, vect, z, k); tdouble c, s, temp_sqr; //c,s - коэффициСнты, temp_sqr - Π²Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹ΠΉ ΠΊΠΎΡ€Π΅Π½ΡŒ for (int i = k + 1; i < n; i++) //сдвигаСмся Π½Π° строчку Π²Π½ΠΈΠ· ΠΈ считаСм: { //подсчСт коэффициСнтов if (abs(mtx[i][k]) < eps) continue; temp_sqr = sqrt(mtx[k][k] * mtx[k][k] + mtx[i][k] * mtx[i][k]); c = mtx[k][k] / temp_sqr; s = mtx[i][k] / temp_sqr; tdouble temp, tempT; for (int j = 0; j < n; j++)//k { //Π·Π°ΠΌΠ΅Π½Π° Π½Π° Π»ΠΈΠ½Π΅ΠΉΠ½Ρ‹Π΅ ΠΊΠΎΠΌΠ±ΠΈΠ½Π°Ρ†ΠΈΠΈ tempT = T[k][j]; T[k][j] = c * T[k][j] + s * T[i][j]; T[i][j] = -s * tempT + c * T[i][j]; if (j >= k) // Ρ‡Ρ‚ΠΎΠ±Ρ‹ лишний Ρ€Π°Π· Π½Π΅ ΠΏΠ΅Ρ€Π΅ΡΡ‡ΠΈΡ‚Ρ‹Π²Π°Ρ‚ΡŒ Π½ΡƒΠ»ΠΈ { temp = mtx[k][j]; //сохраняСм ΠΏΠ΅Ρ€Π²ΡƒΡŽ строку Π²ΠΎ Π²Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ mtx[k][j] = c * mtx[k][j] + s * mtx[i][j]; //замСняСм k-ю строку Π½Π° Π»ΠΊ с коэффициСнтами c ΠΈ s mtx[i][j] = -s * temp + c * mtx[i][j]; //замСняСм j-ю строку Π½Π° Π»ΠΊ с использованиСм ΠΏΠ΅Ρ€Π²ΠΎΠ½Π°Ρ‡Π°Π»ΡŒΠ½ΠΎΠΉ k-ΠΉ строки } } //Π°Π½Π°Π»ΠΎΠ³ΠΈΡ‡Π½ΠΎ с Π²Π΅ΠΊΡ‚ΠΎΡ€ΠΎΠΌ ΠΏΡ€Π°Π²ΠΎΠΉ части temp = vect[k]; vect[k] = c * vect[k] + s * vect[i]; vect[i] = -s * temp + c * vect[i]; temp = sin1[k]; sin1[k] = c * sin1[k] + s * sin1[i]; sin1[i] = -s * temp + c * sin1[i]; temp = sin2[k]; sin2[k] = c * sin2[k] + s * sin2[i]; sin2[i] = -s * temp + c * sin2[i]; temp = sin3[k]; sin3[k] = c * sin3[k] + s * sin3[i]; sin3[i] = -s * temp + c * sin3[i]; temp = sin4[k]; sin4[k] = c * sin4[k] + s * sin4[i]; sin4[i] = -s * temp + c * sin4[i]; } } } void product(tdouble **mtx, tdouble *sol, tdouble *check) { for (int i = 0; i < n; i++) //фиксировали строку { check[i] = 0; for (int j = 0; j < n; j++) //двигаСмся ΠΏΠΎ столбцам ΠΈ.... check[i] += mtx[i][j] * sol[j]; //ΠΏΠ΅Ρ€Π΅ΠΌΠ½ΠΎΠΆΠ°Π΅ΠΌ } } void product(tdouble **mtxun, tdouble **mtxrev, tdouble **mtxcheck) { for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) mtxcheck[i][j] = 0; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { for (int m = 0; m < n; m++) { mtxcheck[i][j] += mtxun[i][m] * mtxrev[m][j]; } } } } void output(tdouble *sol) { for (int i = 0; i < n; i++) cout << fixed << setprecision(4) << setw(42) << sol[i] << endl; } void output(tdouble **mtx, tdouble *vect) { for (int i = 0; i < n; i++) //фиксировали строку { for (int j = 0; j < n + 1; j++) //ΠΏΠΎΠ΅Ρ…Π°Π»ΠΈ ΠΏΠΎ столбцам cout << fixed << setprecision(4) << setw(14) << (j == n ? vect[i] : mtx[i][j]); //Ссли j==n, Ρ‚ΠΎ вывСсти Π²Π΅ΠΊΡ‚ΠΎΡ€ (послСдний столбСц), ΠΈΠ½Π°Ρ‡Π΅ - ΠΌΠ°Ρ‚Ρ€ΠΈΡ†Ρƒ cout << endl; } } void output(tdouble **mtx) { for (int i = 0; i < n; i++) //фиксировали строку { for (int j = 0; j < n; j++) //ΠΏΠΎΠ΅Ρ…Π°Π»ΠΈ ΠΏΠΎ столбцам cout << fixed << setprecision(4) << setw(14) << mtx[i][j]; //Ссли j==n, Ρ‚ΠΎ вывСсти Π²Π΅ΠΊΡ‚ΠΎΡ€ (послСдний столбСц), ΠΈΠ½Π°Ρ‡Π΅ - ΠΌΠ°Ρ‚Ρ€ΠΈΡ†Ρƒ cout << endl; } } void changing(tdouble **mtx, tdouble *vect, int line1, int line2) { tdouble *t = mtx[line2]; //Π·Π°ΠΏΠΎΠΌΠΈΠ½Π°Π΅ΠΌ адрСс mtx[line2] = mtx[line1]; mtx[line1] = t; tdouble r = vect[line2]; vect[line2] = vect[line1]; vect[line1] = r; } void spherical(tdouble *vectun, tdouble *check) { tdouble diff, diff2 = diff = 0.0; for (int i = 0; i < n; i++) { diff += (vectun[i] - check[i]) * (vectun[i] - check[i]); diff2 += vectun[i] * vectun[i] - 2 * vectun[i] * check[i] + check[i] * check[i]; } cout << scientific << endl << "\t\t\t\tНСвязка сфСричСская" << endl << setw(14) << diff << ' ' << setw(14) << diff2 << endl; //os << scientific << endl << "\t\t\t\tНСвязка сфСричСская" << endl << setw(14) << diff << ' ' << setw(14) << diff2 << endl; } tdouble octahedron(tdouble *vectun) { tdouble diffo_2 = 0.0; for (int i = 0; i < n; i++) diffo_2 += abs(vectun[i]); //cout << scientific << endl << "\t\t\t\tНСвязка октаэдричСская" << endl << setw(14) << diff << endl; return diffo_2; // os << scientific << endl << "\t\t\t\tНСвязка октаэдричСская" << endl << setw(14) << diff << endl; } tdouble octahedron(tdouble *vectun, tdouble *check) { tdouble diffo_1 = 0.0; for (int i = 0; i < n; i++) diffo_1 += abs(vectun[i] - check[i]); //cout << scientific << endl << "\t\t\t\tНСвязка октаэдричСская" << endl << setw(14) << diff << endl; return diffo_1; // os << scientific << endl << "\t\t\t\tНСвязка октаэдричСская" << endl << setw(14) << diff << endl; } tdouble cubic(tdouble *vectun, tdouble *check) { tdouble diffc_1 = abs(vectun[0] - check[0]); //максимум модуля ищСтся => Π·Π°ΠΏΠΎΠΌΠΈΠ½Π°Π΅ΠΌ ΡΠ°ΠΌΡƒΡŽ ΠΏΠ΅Ρ€Π²ΡƒΡŽ Ρ€Π°Π·Π½ΠΎΡΡ‚ΡŒ, Π° Π·Π°Ρ‚Π΅ΠΌ с Π½Π΅ΠΉ сравниваСм for (int i = 1; i < n; i++) { if (diffc_1 < abs(vectun[i] - check[i])) diffc_1 = abs(vectun[i] - check[i]); } // cout << scientific << endl << "\t\t\t\tНСвязка кубичСская" << endl << setw(14) << diff << endl; return diffc_1; //os << scientific << endl << "\t\t\t\tНСвязка кубичСская" << endl << setw(14) << diff << endl; } tdouble cubic(tdouble *vectun) { tdouble diffc_2 = abs(vectun[0]); //максимум модуля ищСтся => Π·Π°ΠΏΠΎΠΌΠΈΠ½Π°Π΅ΠΌ ΡΠ°ΠΌΡƒΡŽ ΠΏΠ΅Ρ€Π²ΡƒΡŽ Ρ€Π°Π·Π½ΠΎΡΡ‚ΡŒ, Π° Π·Π°Ρ‚Π΅ΠΌ с Π½Π΅ΠΉ сравниваСм for (int i = 1; i < n; i++) { if (diffc_2 < abs(vectun[i])) diffc_2 = abs(vectun[i]); } // cout << scientific << endl << "\t\t\t\tНСвязка кубичСская" << endl << setw(14) << diff << endl; return diffc_2; //os << scientific << endl << "\t\t\t\tНСвязка кубичСская" << endl << setw(14) << diff << endl; } tdouble cubic_matrix(tdouble **mtxun) { tdouble norm = 0; tdouble maxn = norm; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) norm += abs(mtxun[i][j]); if (norm > maxn) maxn = norm; norm = 0; } norm= maxn; return norm; } tdouble octah_matrix(tdouble **mtxun) { tdouble norm = 0; tdouble maxn = norm; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) norm += abs(mtxun[j][i]); if (norm > maxn) maxn = norm; norm = 0; } norm = maxn; return norm; } 
  • one
    So, somewhere you catch floating point underflow, or you rest against a machine zero for float (there is not so much EMNIP, 1e-12 approximately). - Vesper
  • How to fix it? The matrix is ​​nondegenerate and the qr-algorithm zeros are not terrible. - MGMKLML 2:26 pm

1 answer 1

Well, actually that should be expected. The float data float is (usually) 4 bytes, and double is 8, there is still a long double , it is 10 bytes. Accordingly, the more space per type, the more it stores information and the more accurate the result of the calculation.

If you calculate the condition number , then you understand that this is essentially an indicator of how much a calculation error will affect the final result (the larger the number, the larger the total error).

Therefore, write double (or better long ). If the result is not satisfactory after that, it makes sense to read about compensating calculations, improving accuracy, and so on. Perhaps you will help the article " Everything, point, sailed! We learn to work with floating-point numbers and develop an alternative with fixed decimal precision . ”

  • I need a "float" for the task. So I would write "long double" and I wouldn’t steam myself - MGMKLML
  • Read the article, if it didn’t help, realize long arithmetic in general with int - ah, but in general it is necessary to specify the entire task then. I think in the manual on the subject there are algorithms with high stability. - pavel
  • In the manual they are asked to calculate with the type "double", and then "float". Actually, that's all. I didn’t quite understand, anyway, how to solve this problem in my case - MGMKLML
  • 3
    @MGMKLML may be specifically asked to calculate with both types in order to demonstrate a loss of precision when using a float. The fact is that when you calculate the sum of numbers that have a big difference in the order, a rounding error accumulates. For example, if we add 1e-10 to 1e + 10, then we get everything equal to 1e + 10. It is a pity that you did not bring the resulting inverse matrix - perhaps its numbers are just very different in order from the numbers of the original one. - boeing777
  • @ boeing777 By the way, there seemed to be something like that, in the sense of order. - MGMKLML