Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
26
Добавлен:
21.08.2019
Размер:
11.74 Кб
Скачать
#include <Windows.h>
#include <string>
#include "resource.h";
#include <vector>
#include <ctime>
#include <stdlib.h>
#include <math.h>

using namespace std;

BOOL CALLBACK MainPage(HWND, UINT, WPARAM, LPARAM);

double * calculateMethod(double **, double *, int, bool&);
double **X;
double *B;
double *res;
bool calc;

int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow)
{
	DialogBoxParam(hInstance, MAKEINTRESOURCE(SourcePage), 0, (MainPage), 0);

	return 0;
}

void setArrays(HWND hwnd)
{
	HWND hWnd;
	srand(time(0));

	while (true)
	{
		calc = true;
		for (int i = 0; i < 2; i++)
		{
			for (int j = 0; j < 2; j++)
			{
				X[i][j] = rand() % 100 - 10;
			}
		}
		for (int i = 0; i < 2; i++)
		{
			B[i] = rand() % 100 - 10;
		}

		char buff[50] = {};

		_itoa_s((int)X[0][0], buff, 10);
		hWnd = GetDlgItem(hwnd, a11);
		SetWindowText(hWnd, buff);

		_itoa_s((int)X[0][1], buff, 10);
		hWnd = GetDlgItem(hwnd, a13);
		SetWindowText(hWnd, buff);

		_itoa_s((int)X[1][0], buff, 10);
		hWnd = GetDlgItem(hwnd, a21);
		SetWindowText(hWnd, buff);

		_itoa_s((int)X[1][1], buff, 10);
		hWnd = GetDlgItem(hwnd, a23);
		SetWindowText(hWnd, buff);

		_itoa_s((int)B[0], buff, 10);
		hWnd = GetDlgItem(hwnd, b1);
		SetWindowText(hWnd, buff);

		_itoa_s((int)B[1], buff, 10);
		hWnd = GetDlgItem(hwnd, b2);
		SetWindowText(hWnd, buff);

		res = calculateMethod(X, B, 2, calc);
		if (calc)
			break;
	}
}
#define ID_SM11 1
#define ID_SM12 2
#define ID_SM21 3
#define ID_SM22 4

BOOL CALLBACK MainPage(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch (uMsg)
	{
	case WM_INITDIALOG:
	{
		HMENU hMenubar = CreateMenu();
		HMENU hMenu = CreateMenu();
		HMENU hMenu2 = CreateMenu();
		HMENU hSubMenu = CreatePopupMenu();

		AppendMenu(hMenubar, MF_POPUP, (UINT_PTR)hMenu, "Главная");
		AppendMenu(hMenu, MF_STRING, ID_SM11, "Сгенерировать новую систему уравнений");
		AppendMenu(hMenu, MF_STRING, ID_SM12, "Выход");
		AppendMenu(hMenubar, MF_POPUP, (UINT_PTR)hMenu2, "Справка");
		AppendMenu(hMenu2, MF_STRING, ID_SM21, "Теория");
		AppendMenu(hMenu2, MF_STRING, ID_SM22, "О программе");

		SetMenu(hwnd, hMenubar);
		X = new double*[2];
		for (size_t i = 0; i < 2; i++)
		{
			X[i] = new double[2];
		}
		B = new double[2];
		res = new double[2];

		setArrays(hwnd);

		break;
	}
	case WM_CTLCOLORSTATIC:
		if (GetDlgItem(hwnd, Text1) == (HWND)lParam || GetDlgItem(hwnd, Text2) == (HWND)lParam)
		{
			HDC hdc;
			hdc = (HDC)wParam;

			SetBkMode(hdc, TRANSPARENT);
			SetTextColor(hdc, RGB(1, 1, 81));
			SelectObject(hdc, GetStockObject(BLACK_BRUSH));
			return (INT_PTR)GetSysColorBrush(COLOR_BTNFACE);
		}
		return 0;
	case WM_COMMAND:
	{
		switch (LOWORD(wParam))
		{
		case ID_SM11:
			setArrays(hwnd);
			break;
		case ID_SM12:
			EndDialog(hwnd, 0);
			break;
		case ID_SM21:
			MessageBox(0, "Метод Гаусса в математическом варианте. \n\n 1. Ищем сначала ненулевой элемент в первом столбце.Если все элементы первого столбца нулевые, то переходим ко второму столбцу, и так далее.Если нашли ненулевой элемент в k - й строке, то при помощи элементарного преобразования первого рода меняем местами первую и k - ю строки, добиваясь того, чтобы первый элемент первой строки был отличен от нуля; \n2. Используя элементарные преобразования второго рода, обнуляем все элементы первого столбца, начиная со второго элемента.Для этого от строки с номером k вычитаем первую строку, умноженную на коэффициент ak1 \ a11 .\n3. Переходим ко второму столбцу(или j - му, если все элементы первого столбца были нулевыми), и в дальнейшем рассматриваем только часть матрицы, начиная со второй строки и ниже.Снова повторяем пункты 1) и 2) до тех пор, пока не приведем матрицу к ступенчатому виду.\n\nМетод Гаусса в языке программирования.\n\n1. Индексы строк и столбцов матрицы начинаются с нуля, а не с единицы;\n2. Недостаточно найти просто ненулевой элемент в столбце.В программировании все действия с вещественными числами производятся приближенно, поэтому можно считать, что точного равенства вещественных чисел вообще не бывает.Некоторые компиляторы даже выдают предупреждения на каждую операцию проверки равенства вещественных чисел.Поэтому вместо проверки на равенство нулю числа aij следует сравнивать его абсолютную величину ij с очень маленьким числом ε(например, ε = 0.00000001).Если ij = < ε, то следует считать элемент aij нулевым;\n3. при обнулении элементов j - го столбца, начиная со строки i + 1, мы к k - й строке, где k > i, прибавляем i - ю строку, умноженную на коэффициент\nr = -akj \ aij .\nТакая схема работает нормально только тогда, когда коэффициент r по абсолютной величине не превосходит единицы.В противном случае, ошибки округления умножаются на большой коэффициент и, таким образом, экспоненциально растут.Математики называют это явление неустойчивостью вычислительной схемы.Если вычислительная схема неустойчива, то полученные с ее помощью результаты не имеют никакого отношения к исходной задаче.В нашем случае схема устойчива, когда коэффициент r = -akj \ aij не превосходит по модулю единицы.Для этого должно выполняться неравенство Отсюда следует, что при поиске разрешающего элемента в j - м столбце необходимо найти не первый попавшийся ненулевой элемент, а максимальный по абсолютной величине.Если он по модулю не превосходит ε, то считаем, что все элементы столбца нулевые; иначе меняем местами строки, ставя его на вершину столбца, и затем обнуляем столбец элементарными преобразованиями второго рода.\nОсновная идея метода Гаусса - привести матрицу систему к диагональному виду, то есть все элементы главной диагонали –нули.Для приведения матрицы к такому виду, мы выбираем самую верхнюю строку матрицы, и вычитаем её из всех остальных строк, умножив её для каждой строки на некий коэффициент, так, что самый левый столбец ниже главной диагонали заполнен нулями.Вычитаемая с коэффициентом строка называется текущей строкой.Выбирая текущую строку вначале верхнюю, а потом всё ниже и ниже, мы добьёмся, что все элементы ниже главной диагонали будет равны нулю.Эту часть метода - обработка строк по текущей строке и предстоит распараллеливать.\nСуть метода заключается в последовательном исключении неизвестных.	", "Теория", MB_ICONINFORMATION);
			break;
		case ID_SM22:
			MessageBox(0, "Программа-тренажер \"Система уравнений\" была создана для автоматизации процесса обучения по теме \"Решение системы двух уравнений с двумя неизвестными\", а так же для повышения успеваемости и качества знаний, и для снижения нагрузки педагогу.", "О программе	", MB_ICONINFORMATION);
			break;
		case IDC_BUTTON1:
		{
			HWND hw1, hw2;
			hw1 = GetDlgItem(hwnd, IDC_EDIT1);
			hw2 = GetDlgItem(hwnd, IDC_EDIT2);

			char buff1[50] = {};
			char buff2[50] = {};

			GetWindowText(hw1, buff1, 10);
			GetWindowText(hw2, buff2, 10);

			float tmpItem1 = atof(buff1);
			float tmpItem2 = atof(buff2);

			if (fabs(res[0] - tmpItem1) <= 0.01 && fabs(res[1] - tmpItem2) <= 0.01)
			{
				MessageBox(0, "Верное решение", "Информация", MB_ICONINFORMATION);
			}
			else
			{
				MessageBox(0, "Неверное решение", "Информация	", MB_ICONINFORMATION);
			}
			break;
		}
		case IDC_BUTTON3:
		{
			setArrays(hwnd);
			break;
		}
		}
		break;
	}

	case WM_CLOSE:
	{
		EndDialog(hwnd, 0);
		break;
	}
	}
	return FALSE;
}

double * calculateMethod(double **arr, double *y, int n, bool& calc)
{
	double *x, max;
	int k, index;
	const double eps = 0.00001;
	x = new double[n];
	k = 0;
	while (k < n)
	{
		max = abs(arr[k][k]);
		index = k;
		for (int i = k + 1; i < n; i++)
		{
			if (abs(arr[i][k]) > max)
			{
				max = abs(arr[i][k]);
				index = i;
			}
		}

		if (max < eps)
		{
			//MessageBox(0, "Решение получить невозможно из-за нулевого столбца ", "Error", MB_ICONERROR);
			calc = false;
			return 0;
		}
		for (int j = 0; j < n; j++)
		{
			double temp = arr[k][j];
			arr[k][j] = arr[index][j];
			arr[index][j] = temp;
		}
		double temp = y[k];
		y[k] = y[index];
		y[index] = temp;

		for (int i = k; i < n; i++)
		{
			double temp = arr[i][k];
			if (abs(temp) < eps)
			{
				continue;
			}
			for (int j = 0; j < n; j++)
			{
				arr[i][j] = arr[i][j] / temp;
			}
			y[i] = y[i] / temp;
			if (i == k)
			{
				continue;
			}
			for (int j = 0; j < n; j++)
			{
				arr[i][j] = arr[i][j] - arr[k][j];
			}
			y[i] = y[i] - y[k];
		}
		k++;
	}

	for (k = n - 1; k >= 0; k--)
	{
		x[k] = y[k];
		for (int i = 0; i < k; i++)
		{
			y[i] = y[i] - arr[i][k] * x[k];
		}
	}
	return x;
}
Соседние файлы в папке Project1
  • #
    21.08.20196.55 Кб26Project1.rc
  • #
    21.08.20196.1 Кб27Project1.vcxproj
  • #
    21.08.20191.32 Кб26Project1.vcxproj.filters
  • #
    21.08.2019165 б26Project1.vcxproj.user
  • #
    21.08.20191.37 Кб26resource.h
  • #
    21.08.201911.74 Кб26Source.cpp