БлогNot. C++: СЛАУ методом Гаусса :)

C++: СЛАУ методом Гаусса :)

Старая добрая проблема о решении СЛАУ методом Гаусса, всплыла в аспекте "а есть ли что-то на Си" и т.п.

Есть, прилагаю консольное решение C/C++ отдельной заметкой.

Данные берутся из файла текущей папки с именем gauss.dat. Его формат следующий:

  • Строка описания системы (до 80 символов)
  • Строка с размерностью системы, например, 4
  • Строки матрицы
  • Элементы вектора правой части в столбик.

Например для СЛАУ 4 на 4 может получиться файл:

My System
4
0 35 17.3 2
2 0 1 -1.5
3 17 12.1 14
-9 77.3 122.11 23
1
2
3
4

Сам код мне кажется довольно очевидным, просто приведу его. В конcоли Studio 2015 и т.п. работает.

Интересное в решении - как на C/C++ нумеровать элементы массивов с единицы, а не с нуля :)

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#define ICHAR 80  /*  Длина строки описания системы  */

#define IDEBUG 1  /* Печатать ли шаги декомпозиции */

int matrix_print_off(int nr, int nc, double **A) {
	int i, j;
	if (nr <= 0) return (-1);
	if (nc <= 0) return (-2);
	for (i = 1; i <= nr; i++) {
		for (j = 1; j <= nc; j++) {
			printf("%9.4f  ", A[i][j]);
		}
		printf("\n");
	}
	return (0);
}

int vector_print_off(int nr, double *x) {
	int i;

	if (nr <= 0) return (-1);

	for (i = 1; i <= nr; i++) {
		printf("%9.4f  \n", x[i]);
	}
	printf("\n");
	return (0);
}

double *matrix_on_vector_mult(int nr, int nc, double **A, double *x) {
	if (nr <= 0) return NULL;
	if (nc <= 0) return NULL;
	double *b = (double *)calloc(nr, sizeof(double)); b--;
	for (int i = 1; i <= nr; i++) {
		b[i] = 0;
		for (int j = 1; j <= nc; j++) b[i] += A[i][j] * x[j];
	}
	return b;
}

void gauss(double **a, double *b, double *x, int n) {
	int   i, j, k, m, rowx;
	double xfac, temp, temp1, amax;

	rowx = 0;   
	for (k = 1; k <= n - 1; ++k) {
		amax = (double)fabs(a[k][k]);
		m = k;
		for (i = k + 1; i <= n; i++) {  
			xfac = (double)fabs(a[i][k]);
			if (xfac > amax) { amax = xfac; m = i; }
		}
		if (m != k) { 
			rowx = rowx + 1;
			temp1 = b[k];
			b[k] = b[m];
			b[m] = temp1;
			for (j = k; j <= n; j++) {
				temp = a[k][j];
				a[k][j] = a[m][j];
				a[m][j] = temp;
			}
		}
		for (i = k + 1; i <= n; ++i) {
			xfac = a[i][k] / a[k][k];

			for (j = k + 1; j <= n; ++j) {
				a[i][j] = a[i][j] - xfac*a[k][j];
			}
			b[i] = b[i] - xfac*b[k];
		}

		if (IDEBUG == 1) {
			printf("\n Decomposition step %d\n\n", k);
			matrix_print_off(n, n, a);
		}
	}

	for (j = 1; j <= n; ++j) {
		k = n - j + 1;
		x[k] = b[k];
		for (i = k + 1; i <= n; ++i) {
			x[k] = x[k] - a[k][i] * x[i];
		}
		x[k] = x[k] / a[k][k];
	}

	if (IDEBUG == 1) printf("\nNumber of row exchanges = %d\n", rowx);
}

int main(void) {
	double  **a, **a0, *b, *x;
	float  aij, bi;
	char   desc[ICHAR];
	int    i, j, n;
	FILE   *finput;

    finput = fopen("gauss.dat", "r");
	if (finput == NULL) {
		printf("Data file gauss.dat not found\n");
		return(-1);
	}
		
	fgets(desc, ICHAR, finput);
	fscanf(finput, "%d", &n);
	printf("%s", desc);
	printf("\nDimension of matrix = %d\n\n", n);

	a = (double **)calloc(n, sizeof(double *)); --a; //Для нумерации с единицы :)
	a0 = (double **)calloc(n, sizeof(double *)); --a0; //Копия матрицы для проверки решения

	for (i = 1; i <= n; ++i) {
		a[i] = (double *)calloc(n, sizeof(double)); --a[i];
		a0[i] = (double *)calloc(n, sizeof(double)); --a0[i];
	}

	b = (double *)calloc(n, sizeof(double)); --b;
	x = (double *)calloc(n, sizeof(double)); --x;

	for (i = 1; i <= n; i++) {
		for (j = 1; j <= n; j++) {
			fscanf(finput, "%f ", &aij);
			a[i][j] = (double)aij;
			a0[i][j] = (double)aij;
		}
	}

	for (i = 1; i <= n; i++) {
		fscanf(finput, "%f ", &bi);
		b[i] = (double)bi;
	}

	fclose(finput); 

	printf("\nMatrices read from input file\n");

	printf("\nMatrix A\n\n");
	matrix_print_off(n, n, a);

	printf("\nVector b\n\n");
	vector_print_off(n, b);

	gauss(a, b, x, n);

	printf("\nSolution x\n\n");
	vector_print_off(n, x);

	if (IDEBUG == 1) {
		double *b0 = matrix_on_vector_mult(n, n, a0, x);
		printf("\nChecking\n\n");
		vector_print_off (n, b0);
	}

	getchar();
	return(0);
}

28.09.2017, 15:44 [13664 просмотра]


теги: c++ учебное алгоритм

показать комментарии (1)