Показать сообщение отдельно
  #6  
Старый 31.08.2012, 23:08
PIF85 PIF85 вне форума
Прохожий
 
Регистрация: 18.12.2008
Сообщения: 17
Репутация: 10
По умолчанию

Нашел в интернете алгоритм ( а точнее код) расстановки коэффициентов в уравнениях химических реакций методом Гаусса-Жордана (как я понял это метод решения систем линейных уравнений). Опять-таки, то, что смог понять из этого кода, так это то, что сначала создается матрица элементов (чисел), затем матрица преобразуется в систему линейных уравнений, которые решаются и из этих уравнений находятся коэффициенты для всех веществ хим. реакции. Проблеме в том, что код написан (как я понял) на С++. Мне и в паскалевском коде такой сложности трудно ориентироваться, а тут тем более.
Код:
/*** Решение уравнений методом Гаусса - Жордана ***/
#include <math.h>
#define GAUSS_ACCURACY 0.0000001
#define GAUSS_OK 0
#define GAUSS_NOSOL 1
#define GAUSS_MANYSOL 2

/*********************************************/
/* Функция решения систем линейных уравнений */
/* методом Гаусса - Жордана                  */
/* (C) 2002 Восков Алексей                   */
/* версия 2.1                                */
/*********************************************/
/* ВХОДНЫЕ ДАННЫЕ */
/* a[20][20] - Матрица для хранения системы a[y][x]
	       последний столбец - для хранения св. члена
	       св. член - в правой части
   n - число неизвестных
   u - число уравнений
   ВЫХОДНЫЕ ДАННЫЕ
   x[20] - массив для хранения корней системы

   в случае нормального выполнения задачи функция
   возвращает 0, в случае неразрешимости 1
   в случае бесконечного числа решений 2 */
int gauss(double a[20][20], int n, int u, double x[20])
{
	int i, j, k;        /* Счетчики циклов */
	int sn;             /* Номер строки */
	double d;           /* Коэффициент домножения или модуль наиб. эл. */

	/*** Проверка u и n ***/
	if (n > u) return 2;

	/*** Приведение к диагональному виду ***/
	for (j = 0; j < n; j++)
	{
		/* а) поиск строки с наибольшим по модулю элементом */
		d = fabs(a[j][j]); sn = j;
		for (i = j; i < u; i++)
			if (fabs(a[i][j]) > d)
			{
				d = fabs(a[i][j]);
				sn = i;
			}

		/* б) перенос строки на надлежащее место */
		for (k = 0; k <= n; k++)
		{
			d = a[sn][k];
			a[sn][k] = a[j][k];
			a[j][k] = d;
		}

		/* в) деление ведущего ур-я на главный элемент */
		d = a[j][j];

		if (d)
			for (k = 0; k <= n; k++) a[j][k] /= d;
		else
			for (k = 0; k <= n; k++) a[j][k] = 0;

		/* г) вычитание данной строки из всех остальных */
		/*    с домножением на коэффициент */
		for (i = 0; i < u; i++)
		{
			if (i == j) continue;  /* Не трогаем вычит. строку */
			d = -a[i][j];
			for (k = 0; k <= n; k++) /* Вычитание */
				a[i][k] += a[j][k] * d;
		}
	}

	/*** Вычисление корней ***/
	/* а) проверка системы на разрешимость */
	if (u > n)
	{
		for (i = n; i < u; i++)
		{
			k = 0;
			for (j = 0; j < n; j++)
				if (fabs(a[i][j]) > GAUSS_ACCURACY) k = 1;
			if (k == 0 && fabs(a[i][n]) > GAUSS_ACCURACY) return 1;
		}
	}

	/* б) поиск корней */
	for (i = 0; i < n; i++)
	{
		x[i] = -a[i][n];
		if (a[i][i] != 1) /** Обработка ошибок **/
		{ if (x[i])
			return GAUSS_NOSOL; /* Решений нет */
		  else
			return GAUSS_MANYSOL; /* Бесконечно много решений */
		}
		if (fabs(x[i]) < GAUSS_ACCURACY) x[i] = 0; /* Обнуление слишком малых знач. */
	}
	return GAUSS_OK; /* Нормальное завершение работы */
}
Собственно ссылка на описание метода:
http://ru.wikipedia.org/wiki/%D0%9C%D0%B5%D1%82%D0%BE%D0%B4_%D0%93%D0%B0%D1%83% D1%81%D1%81%D0%B0_%E2%80%94_%D0%96%D0%BE%D1%80%D0% B4%D0%B0%D0%BD%D0%B0
Выкладываю программу которая основана на этом принципе расстановки коэффициентов. Для примера, можно уравнять реакцию: NaCl+H2SO4+KMnO4=Cl2+MnSO4+Na2SO4+K2SO4+H2O
c_urav.zip
Буду благодарен за перевод кода на Delphi и если возможно, подробное пояснения кода.
Спасибо Всем большое!
Ответить с цитированием