Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 30.11.2009, 21:13   #1
alexobenikov
Пользователь
 
Регистрация: 19.11.2009
Сообщений: 15
По умолчанию Проблема с калькулятором для матриц на С

В общем проблема следующая:
1.Я могу написать обычный калькулятор для чисел , а вот для матриц нет т.к. :
Для чисел я считал так : (данный пример без скобок , но в них проблем нет) для примера 2*4-3
Я сначала считаю 2*4 , и моя строка принимает вид 8-3 , далее считаю ее.Но для примера А*4-3 такой прикол не пойдет (А - квадратная заданная матрица, а числа я просто домножаю на единичную матрицу , и далее рассматриваю операции для матриц) но тут посчитав значение А*4 у меня проблема т.к. надо создать новую матрицу например В , и далее уже работать с ней.
Понимаю что надо работать с malloc , но ее я плохо знаю (синтаксис понимаю , но не совсем пойму как ее правильно надо втулить сюда (не могли бы с этим помочь) )
alexobenikov вне форума Ответить с цитированием
Старый 30.11.2009, 21:18   #2
NiCola999
Не
Участник клуба
 
Регистрация: 29.10.2009
Сообщений: 1,456
По умолчанию

Цитата:
Но для примера А*4-3 такой прикол не пойдет
насколько я помню из математики при умножении матрицы на число, просто перемножаются все элементы матрицы на это число, аналогично +-/ с числом.Дополнительная матрица тут вовсе не нужна. Действуйте также как и для обычных чисел, только вместо простых операций будут функции работы с матрицами. malloc думаю там не понадобится.При операциях матрица*/+-матрица, можно результирующую матрицу класть в исходную

Последний раз редактировалось NiCola999; 30.11.2009 в 21:27.
NiCola999 вне форума Ответить с цитированием
Старый 30.11.2009, 21:20   #3
Pashan
Пользователь
 
Регистрация: 18.03.2009
Сообщений: 89
По умолчанию

Ты хоть какой-нибудь код приведи, что-ли. А то сложно понять, как это все реализовано и как лучше доделывать.
Pashan вне форума Ответить с цитированием
Старый 30.11.2009, 21:46   #4
alexobenikov
Пользователь
 
Регистрация: 19.11.2009
Сообщений: 15
По умолчанию

NiCola999 я умножаю на единичную для того , что бы потом пользоваться умножением для матриц.
По большому счету задача вообще не сделана т.к. есть пока (помимо всяких чисто декоративных вещей) только операции над матрицами,но если это поможет
Код:
typedef struct
{
	double a[10][10];
	int n;
}matrix;
matrix mul(matrix b,matrix a)//определяем операцию умножение (mul) для матриц 
{ 
	matrix z;
	for (int k=0;k<a.n;k++)
	{
		for (int i=0;i<a.n;i++)
		{
			for(int j=0;j<a.n;j++)
			{
				z.a[i][j]=a.a[i][k]*b.a[k][j];
			}
		}
	}

	
	return z;
}
matrix sum(matrix a,matrix b)//определяем операцию суммы (sum) для матриц
{
	matrix f;
	for(int i=0;i<a.n;i++)
	{
		for(int j=0;j<a.n;j++)
		{
			f.a[i][j]=a.a[i][j]+b.a[i][j];
		}
	}
	return f;
}
matrix razn(matrix a,matrix b)
{
	matrix f;
	for(int i=0;i<a.n;i++)
	{
		for(int j=0;j<a.n;j++)
		{
			f.a[i][j]=a.a[i][j]-b.a[i][j];
		}
	}
	return f;
}
matrix del(matrix a,matrix b)
{
	matrix l;
	matrix c;//обратная матрица тоесть с=в^(-1)
	
	c=obrat(b);
	l=mul(a,c);

	return l;
}
matrix obrat(matrix a)
{
	matrix r;

	for (int i=0;i<a.n;i++)
	{
		for (int j=0;j<a.n;j++)
		{
			int p=1;
			if ((i+j)%2==1)
			{
				p=-1;
			}
			r.a[i][j] =p*determinant(obrez(a,j,i));
		}

	}

	
	return r;
}
matrix obrez (matrix a, int m,int k)
{
	matrix b;
	
	b.n=a.n-1;

		for (int i=0;i<a.n;i++)
		{
			for (int j=0;j<a.n;j++)
			{
				if (i<m && j<k)
					b.a[i][j]=a.a[i][j];
				if (i>m && j<k)
					b.a[i][j]=a.a[i-1][j];
				if (i<m && j>k)
					b.a[i][j]=a.a[i][j-1];
				if (i>m && j>k)
					b.a[i][j]=a.a[i-1][j-1];
			}
		}

	return b;
}
double determinant(matrix x)
{
	if (x.n==2) return x.a[1][1]*x.a[2][2]-x.a[1][2]*x.a[2][1];
	
	matrix y;
	double det=0;
	for (int i=1; i<=x.n; i++)
	{
		int p=1; 
		if (i%2==0) p=-1; 
		y.n=x.n-1;  

		int ver; 
		for (int j=2; j<=x.n; j++)
		{
			ver=0;
			for (int k=1; k<=x.n; k++)
				if (k!=i)
				{
					ver++;
					y.a[j-1][ver]=x.a[j][k];
				}
		}

		det=det + p*x.a[1][i]*determinant(y);
	}

	return det;
}
matrix preobrazovanie_int_v_matrix(int x,int n)
{
	matrix b;

	for (int i=0;i<n;i++)
	{
		for (int j=0;j<n;j++)
		{
			if (i==j)
				b.a[i][j]=x;
			else b.a[i][j]=0;
		}
	}

	return b;
}
PS заранее прошу не смеяться=)
alexobenikov вне форума Ответить с цитированием
Старый 30.11.2009, 21:59   #5
NiCola999
Не
Участник клуба
 
Регистрация: 29.10.2009
Сообщений: 1,456
По умолчанию

ну всё хорошо кроме

Код:
matrix mul(matrix b,matrix a)//определяем операцию умножение (mul) для матриц 
{ 
	matrix z;
	for (int k=0;k<a.n;k++)
	{
		for (int i=0;i<a.n;i++)
		{
			for(int j=0;j<a.n;j++)
			{
				z.a[i][j]=a.a[i][k]*b.a[k][j];
			}
		}
	}

	
	return z;
}
зачем создавать дополнтельную матрицу, если можно результирующую матрицу положить в первую.

Цитата:
я умножаю на единичную для того , что бы потом пользоваться умножением для матриц.
помоему это немного не разумно. У тебя итак в функции перемножения 3 цикла, так ты будешь при умножении на число умножать на единичную потом на саму матрицу. Прикинь сколько ты теряешь в производительности твоего калькулятора.Если ты будешь считать выражения типа
A*5*6*7*8*9*2*3*4*233*3*3333*3*33*3 33*3 итд
то калькулятор будет довольно долго перемножать эти матрицы...

почему нельзя сделать простые функции для операций типа матрица (операнд) число
вот для примера умножение на число

Код:

matrix mulK(matrix b,int a)//определяем операцию умножение (mul) для матриц 
{ 
	for (int i=0;k<b.n;i++)
	{
		for (int j=0;i<b.n;j++)
		    b.a[i][j]*=a;
	}
	return b;
}
а так всё нормально, осталось сделать ввод выражения, расстановка приоритетов и вперед =)

Последний раз редактировалось NiCola999; 30.11.2009 в 22:05.
NiCola999 вне форума Ответить с цитированием
Старый 30.11.2009, 22:11   #6
Pashan
Пользователь
 
Регистрация: 18.03.2009
Сообщений: 89
По умолчанию

alexobenikov, а кода самого калькулятора нет?

То есть, как я понимаю, пользователь вводит строку: "A*2+1" (Допустим, у нас есть матрица А и 1 - это единичная матрица). Надо это все посчитать. Тогда один из простых способов - рекурсивный вызов одной и той же функции. Например:

matrix calculate(char* str)

Она получает строку "А*2+1" и находит в ней оператор, который должен выполнится последним (здесть это "+"). Потом разбивает строку на две подстроки: "А*2" и "1" и вызывает сама себя, то есть типа такого:

case '+': return calculate("A*2") + calculate("1");

допустим, calculate("1") вернет единичную матрицу, а calculate("A*2") пойдет тем же путем - найдет операцию умножения, и:

case '*': return calculate("A") * calculate("2")

Ну это условно. Тогда никакого геморроя с промежуточными значениями не будет - они посчитаются "на лету".

P.S.
А для матриц неплохо бы класс завести и операторы +, -, * перегрузить. Тогда код будет горазда читабельней. Но это уж как хочешь.
Pashan вне форума Ответить с цитированием
Старый 01.12.2009, 18:28   #7
alexobenikov
Пользователь
 
Регистрация: 19.11.2009
Сообщений: 15
Лампочка

Хорошо, давайте разберем пример ( 2*А-3*В-4*А ) *A
наше выражение станет
calculatе ( calculate( 2*А ) - calculate( 3*В ) - calculate (4*A) ) * calculate ( A )
далее каждый из calculate тоже расподается до "простых" символов и.т.д.

я примерно сделал набросок
Код:
matrix count(char* a , char* b)
{
	int n = (b-a)/sizeof(char);
	for (int i=0;i<n;i++)
	{
		if ( a[i] == '+' )
			return sum ( count(a,&a[i-1]) , count(&a[i+1] , &b ) );
		if ( a[i] == '-' )
			return razn (count(a,&a[i-1]) , count(&a[i+1] , &b ) );
	}

	for (int i=0;i<n;i++)
	{
		if ( a[i] == '*' )
			return mul (count(a,&a[i-1]) * count(&a[i+1] , &b ) );
		if ( a[i] == '/' )
			return del (count(a,&a[i-1]) / count(&a[i+1] , &b ) );
	}

}
но у меня выдает ошибку : cannot convert parameter 2 from 'char **__w64 ' to 'char *' (не судите строго , я только вшариваюсь в указатели)



Цитата:
зачем создавать дополнтельную матрицу, если можно результирующую матрицу положить в первую.
ну просто ,если не ошибаюсь, то так у нас будет меняться сама исходная матрица (например 2*А) и потом если мы где-то используем А - то оно будет считаться - что мы использовали 2*А
alexobenikov вне форума Ответить с цитированием
Старый 01.12.2009, 19:16   #8
Pashan
Пользователь
 
Регистрация: 18.03.2009
Сообщений: 89
По умолчанию

Ошибка из-за того, что ты берешь адрес b, хотя это и есть указатель.
вместо
return sum ( count(a,&a[i-1]) , count(&a[i+1] , &b ) );
неплохо бы
return sum ( count(a, a + i - 1) , count(a + i + 1 , b ) );
Pashan вне форума Ответить с цитированием
Старый 01.12.2009, 19:24   #9
Pashan
Пользователь
 
Регистрация: 18.03.2009
Сообщений: 89
По умолчанию

Цитата:
ну просто ,если не ошибаюсь, то так у нас будет меняться сама исходная матрица (например 2*А) и потом если мы где-то используем А - то оно будет считаться - что мы использовали 2*А
Так, как у тебя задано, исходная матрица А не должна меняться (при передаче в функцию создастся новая структура и в нее скопируются значения). Но с мнением об использовании одного из параметров для результата я категорически не согласен. Это из серии "шаманства", когда ты сам через два дня забудешь, зачем это сделано. К тому же сложные параметры в функции любят передавать по ссылке (const matrix& A). Тогда будет верен твой вариант об изменении исходной А, а внешне вызов функции никак не изменится. Кстати, в твоем случае сделать передачу по ссылке вполне разумно.
Pashan вне форума Ответить с цитированием
Старый 03.12.2009, 18:37   #10
alexobenikov
Пользователь
 
Регистрация: 19.11.2009
Сообщений: 15
По умолчанию

В общем написал свою прогу - но она не правильно считает - не подскажите где может быть загвоздка

Код:
#include <stdio.h>
#include <iostream>

typedef struct
{
	double a[10][10];
	int n;
}matrix;

int razmer;

matrix count (char* a ,char* b );
matrix mul(matrix a,matrix b);
matrix sum(matrix a,matrix b);
matrix razn(matrix a,matrix b);
matrix del(matrix a,matrix b);
matrix obrat(matrix a);
matrix obrez(matrix a,int m,int k);
double determinant(matrix x);
matrix preobrazovanie_int_v_matrix(char x ,int n);

matrix* p_A;
matrix* p_B;

int main()
{
	matrix A;
	matrix B;
	p_A=&A;
	p_B=&B;

	char vir[50];
	matrix otvet;
		
	printf("Vvedite rang (ne bolshe 10) dla matric A i B \n");
	scanf("%d",&A.n);
	B.n=A.n;
	razmer=A.n;

	printf("Vvedite matricu A %d-go ranga\n",A.n);
	for (int i=0; i<A.n; i++)
		for (int j=0; j<A.n; j++)
			scanf("%d",&A.a[i][j]);

	printf("Vvedite matricu B %d-go ranga\n",B.n);
	for (int i=0; i<B.n; i++)
		for (int j=0; j<B.n; j++)
			scanf("%d",&B.a[i][j]);


	printf("Vvedite viraszhenie: \n");
	scanf("%s",vir);

	int n=strlen(vir);

	otvet=count(vir , vir+n-1);

	for (int i=0; i<B.n; i++)
		for (int j=0; j<B.n; j++)
		{
			printf("%d\n",otvet.n);
		}


	
	return 0;
}


matrix count ( char* a, char* b)
{
	int n = (b-a)/sizeof(char);

	for (int i=0;i<n;i++)
	{
		if ( a[i] == '+' )
			return sum (count(a,a+i-1) , count(a+i+1 , b ) );
		if ( a[i] == '-' )
			return razn (count(a,a+i-1) , count(a+i+1 , b ) );
	}

	for (int i=0;i<n;i++)
	{
		if ( a[i] == '*' )
			return mul( count(a,a+i-1) , count(a+i+1 , b ) );
		if ( a[i] == '/' )
			return del( count(a,a+i-1) , count(a+i+1 , b ) );
	}

	for (int i=0;i<n;i++)
	{
		if ( a[i] == 'A')
			return *p_A; // переделать  операции для указателей и возвращать тогда p_A 
		
		if ( a[i] == 'B')
			return *p_B;

		if (isdigit(a[i]))
			return preobrazovanie_int_v_matrix ( a[i] ,razmer );
	}

}			
matrix mul(matrix b,matrix a)//определяем операцию умножение (mul) для матриц 
{ 
	matrix z;
	for (int k=0;k<a.n;k++)
	{
		for (int i=0;i<a.n;i++)
		{
			for(int j=0;j<a.n;j++)
			{
				z.a[i][j]=a.a[i][k]*b.a[k][j];
			}
		}
	}

	
	return z;
}
matrix sum(matrix a,matrix b)//определяем операцию суммы (sum) для матриц
{
	matrix f;
	for(int i=0;i<a.n;i++)
	{
		for(int j=0;j<a.n;j++)
		{
			f.a[i][j]=a.a[i][j]+b.a[i][j];
		}
	}
	return f;
}
matrix razn(matrix a,matrix b)
{
	matrix f;
	for(int i=0;i<a.n;i++)
	{
		for(int j=0;j<a.n;j++)
		{
			f.a[i][j]=a.a[i][j]-b.a[i][j];
		}
	}
	return f;
}
matrix del(matrix a,matrix b)
{
	matrix l;
	matrix c;//обратная матрица тоесть с=в^(-1)
	
	c=obrat(b);
	l=mul(a,c);

	return l;
}
matrix obrat(matrix a)
{
	matrix r;

	for (int i=0;i<a.n;i++)
	{
		for (int j=0;j<a.n;j++)
		{
			int p=1;
			if ((i+j)%2==1)
			{
				p=-1;
			}
			r.a[i][j] =p*determinant(obrez(a,j,i));
		}

	}

	
	return r;
}
matrix obrez (matrix a, int m,int k)
{
	matrix b;
	
	b.n=a.n-1;

		for (int i=0;i<a.n;i++)
		{
			for (int j=0;j<a.n;j++)
			{
				if (i<m && j<k)
					b.a[i][j]=a.a[i][j];
				if (i>m && j<k)
					b.a[i][j]=a.a[i-1][j];
				if (i<m && j>k)
					b.a[i][j]=a.a[i][j-1];
				if (i>m && j>k)
					b.a[i][j]=a.a[i-1][j-1];
			}
		}

	return b;
}
double determinant(matrix x)
{
	if (x.n==2) return x.a[1][1]*x.a[2][2]-x.a[1][2]*x.a[2][1];
	
	matrix y;
	double det=0;
	for (int i=1; i<=x.n; i++)
	{
		int p=1; 
		if (i%2==0) p=-1; 
		y.n=x.n-1;  

		int ver; 
		for (int j=2; j<=x.n; j++)
		{
			ver=0;
			for (int k=1; k<=x.n; k++)
				if (k!=i)
				{
					ver++;
					y.a[j-1][ver]=x.a[j][k];
				}
		}

		det=det + p*x.a[1][i]*determinant(y);
	}

	return det;
}
matrix preobrazovanie_int_v_matrix(char x,int n)
{
	matrix b;

	for (int i=0;i<n;i++)
	{
		for (int j=0;j<n;j++)
		{
			if (i==j)
				b.a[i][j]=(int)x;
			else b.a[i][j]=0;
		}
	}

	return b;
}
alexobenikov вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Обработка Матриц(Упорядочивание Элементов,Вывод На Экран Матриц При Условии...) timepoka Помощь студентам 8 01.07.2011 13:20
функции для формирования и обработки матриц aka_faith Общие вопросы C/C++ 0 15.05.2009 01:40
Помогите с калькулятором vishnya454 Помощь студентам 8 07.01.2009 10:35
Проблема з калькулятором carbon383 Помощь студентам 22 02.11.2008 11:49
Проблемы с калькулятором MAKEDON Помощь студентам 18 02.08.2008 14:30