Определитель матрицы NxN

Модераторы: Hawk, Romeo, Absurd, DeeJayC, WinMain

Аватара пользователя
somewhere
Сообщения: 1858
Зарегистрирован: 31 авг 2006, 17:14
Откуда: 71 RUS
Контактная информация:

&quot писал(а):А вы случаем полную проблему не пробовали решать?
В каком смысле?
It's a long way to the top if you wanna rock'n'roll
Аватара пользователя
Z1ppeR
Сообщения: 4
Зарегистрирован: 04 янв 2008, 13:33

Привожу код на C++ (не мой=))

Используется рекурсия и динамическое распределение памяти

Код: Выделить всё

#include <iostream.h> 
#include <conio.h> 
#include <math.h> 
 
int** csmatr(int**,int);     // --- Функция создания и вывода матрицы ------- 
double determinant(int**,int);  // --- Функция вычисления определителя --------- 
 
void main(void) 
{ 
  int **a,i,N,**matr; 
// --------------------    Указываем порядок матрицы ------------------------ // 
  clrscr(); 
  cout<<"Введите порядок матрицы: "; cin>>N; 
  cout<<'\n'; 
// -------------------- Создание матрицы и вывод ее на экран ------------- // 
  a=csmatr(matr,N); 
// -------------------- Вывод определителя на экран ---------------------- // 
  cout<<"Определитель матрицы = "<<determinant(a,N); 
// --------------------    Освобождение памяти ------------------------------ // 
  for (i=0;i<=N-1;i++) delete a[i]; 
  delete a; 
 
  getch(); 
} 
 
 
/*--------------------------------------------------------------------------- 
          Функция создания матрицы (обязательно должен быть динамический массив) 
---------------------------------------------------------------------------*/ 
int** csmatr(int **matr,int N) 
{ 
  int i,j; 
 
// --------------------    Формирование строк матрицы ----------------------- // 
  matr=new int*[N]; 
// --------------------    Формирование столбцов матрицы -------------------- // 
  for (i=0;i<=N-1;i++)   {matr[i]=new int[N];} 
 
 return matr; 
 
} 
 
 
/*--------------------------------------------------------------------------- 
            Функция вычисления определителя (должна быть обязательно рекурсия) 
---------------------------------------------------------------------------*/ 
double determinant(int **a, int N) 
{ 
  int i,j; 
  int **matr1; 
/*  int sign=1;*/ 
  double determ=0; 
 
  if (N==2) 
  { 
    determ=a[0][0]*a[1][1]-a[0][1]*a[1][0]; 
  } 
  else 
  { 
    matr1=new int*[N-1]; 
 
    for(i=0;i<N;i++) 
    { 
      for(j=0;j<N-1;j++) 
    { 
      if(j<i)   {matr1[j]=a[j];} 
      else      {matr1[j]=a[j+1];} 
    } 
      determ+=pow(-1,(i+j))*determinant(matr1,N-1)*a[i][N-1]; 
    } 
    delete matr1; 
  } 
 
  return determ; 
  cout<<'\n'; 
} 
Пожалуйста модеры или еще кто-нибудь, вы опытны, расскажите что здесь происходит!! Сам понимаю не до конца. Тут какие-то указатели на указатели. А самое важное то, что нет фактического присвоения значений. Думаю заполнить всю матрицу случайными числами, но как это сделать, что добавить в этот конкретный код?
Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

Вот, господа, достатоно элегантный алгоритм для вычисления определителя именно тем способом, который предлагал я. Обратите внимание, что при формирование матрицы N-1 степени даже не создаётся полностью новая матрица, а просто используются поинтеры на строки матрицы N порядка. Такой оптимизации можно добиться расклыдывая матрицу по последнему столбцу.

Z1ppeR, чтобы заполнить матрицу случайными числами нужно изменить вот этот код:

Код: Выделить всё

for (i=0;i<=N-1;i++)   {matr[i]=new int[N];} 
На такой код:

Код: Выделить всё

for (i=0;i<=N-1;i++) 
{
   matr[i]=new int[N];
   for (j=0;j<=N-1;j++)
   {
      matr[i][j] = srand() % 100;
   }
} 
В этом случае матрица будет заполнена целыми числами от 0 до 99.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

Одно замечание к коду: определитель не будет вычисляться, если порядок матрицы равен 1. Чтобы это исправить, нужно добавить ещё одну проверку в функции determinant на то, что N равно 1 и если это так, возвращать a[0][0].
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Аватара пользователя
Z1ppeR
Сообщения: 4
Зарегистрирован: 04 янв 2008, 13:33

Исправил как вы написали, но он выдает ошибку "Not an allowed type" в строке
matr[j] = srand() % 100; И еще ругается по поводу пустых скобок srand()
Ох уж эти указатели. . .
Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

Извиняюсь, там должен стоять rand. Вызов srand тоже нужен, но в самом начале программы для инициализации генератора случайных чисел. Делается это вот так:

Код: Выделить всё

time_t t;
srand((unsigned) time(&t));
Для того, чтобы всё работало нужно не забыть включить соответствующие инклюды:

Код: Выделить всё

#include <stdlib.h>
#include <time.h>
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Аватара пользователя
Z1ppeR
Сообщения: 4
Зарегистрирован: 04 янв 2008, 13:33

Romeo спасибо!! Все работает!! Еще вопрос - в функции main стоит getch()
Я читал про этот оператор, он как-то манипулирует вводом, и с ним используется иногда еще один (не помню какой), но никак не понял как он работает. Зачем он здесь?
Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

Функция getch (сокращение от английского "get char") ждёт до нажатия любой не системной клавиши и как только какая-либо несистемная клавиша нажата возвращает ASCII код этой клавиши. Под системными клавишами в данном случае подразумеваются клавиши CTRL, ALT, SHIFT, PRT SCR, PAUSE, а также toggle клавиши (CAPS LOCK, NUM LOCK, SCROLL LOCK).

В твоей программе результат, возвращаемый функцией getch не анализируется, поэтому еденственная причина, для которой она здесь использована, это добиться приостановки исполнения программы для того, чтобы пользователь смог увидеть результаты её работы.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Ответить