Форум программистов, компьютерный форум CyberForum.ru
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 11, средняя оценка - 4.82
Nuclear_Razor
49 / 2 / 0
Регистрация: 22.07.2012
Сообщений: 104
Записей в блоге: 1
Завершенные тесты: 1
#1

Подстроение алгоритма определителя - C++

25.08.2012, 15:12. Просмотров 1440. Ответов 16
Метки нет (Все метки)

Доброго времени суток уважаемые форумчане! Мне уже надоело искать нормальный и рабочий алгоритм для вычисления определителя. Есть два кода: первый - мой, для решения СЛАУ методом Гаусса, а второй - это рабочий для вычисления определителя (считает все верно), проблема в том, что не могу второй алгоритм подстроить под мою программу, матрицы размером 3x3 уже считает неверно....прошу вашей помощи.

Основная часть кода моей программы:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
    
int  a[10][10];
int  I=0, J=0;
 
        cout <<"\nВведите кол-во строк в матрице :\n";scanf("%d",&I);
    cout <<"\nВведите кол-во столбцов в матрице :\n";scanf("%d",&J);
    
    cout << "Введите элементы матрицы:\n";
 
        for(int i=0;i<I;i++)
            for(int j=0;j<J;j++)
                scanf("%d",&a[i][j]);
 
    cout << "Введенная матрица имеет вид:\n";
    
 
        for (int i=0;i<I;i++)
        {
            for(int j=0;j<J;j++)
    
            printf("\t%6.1d",a[i][j]);
            printf("\n");
        }
 
//Определитель
int j,x,y;
double k;
for (x=0;x<(I-1);x++)
{
 
for (y=(x+1);y<I;y++)
{
k=-a[y][x]/a[x][x];
for (j = 0;j< I;j++)
{
        a[y][j]+=k*a[x][j];
        if (abs(a[y][j]) < EPS) a[y][j]=0;
}
}
}
int det=1;
for(int i=0;i<I;i++)
det*=a[i][i];
 
 cout <<"\nОпределитель:" << det << "\n";
Полный код для вычисления определителя:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#include "stdafx.h"
#include <iostream>
#include <conio.h>
#include <stdlib.h>
#include <math.h>
#define ESP 0.000000001
 
using namespace std;
 
int n;
double d;
 
void imas(double** X,int n);
void omas(double** X,int n);
void det(double** a,int n);
//void max(double** a,int x);
 
void main()
{
cout << "\nrazmernoct kvadratnoi matrix A(nxn)";
 
cin >> n;
double **A;
A=(double**)calloc(n,sizeof(double)); //Amn
for(int i=0;i<n;i++)
A[i]=(double*)calloc(n,sizeof(double));
 
imas(A,n);
omas(A,n);
det(A,n);
delete A;
getch();
}
//-----------------------------------
void imas(double** X,int n)
{
cout << "\nVvod matrix "<<n <<" x "<<n <<"\n";
int i,j;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
cin >> X[i][j];
}
 
void omas(double** X,int n)
{
int i,j;
for(i=0;i<n;i++)
{
cout <<"\n";
for( j=0;j<n;j++)
cout<< X[i][j]<<"\t";
}
cout << "\n";
}
 
void det(double** a,int n)
{
int j,x,y;
double k;
for (x=0;x<(n-1);x++)
{
 
for (y=(x+1);y<n;y++)
{
k=-a[y][x]/a[x][x];
for (j = 0;j< n;j++)
{
a[y][j]+=k*a[x][j];
if (fabs(a[y][j]) < ESP) a[y][j]=0;
}
}
}
double det=1;
for(int i=0;i<n;i++)
det*=a[i][i];
cout <<"\ndet= "<< det;
}
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
25.08.2012, 15:12
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Подстроение алгоритма определителя (C++):

Оптимизация алгоритма вычисления определителя матрицы - C++
Здравствуйте! Написал я давеча программку, которая считает определитель. Только вот беда - он не считает определители матриц выше 10...

Улучшение алгоритма вычисления определителя матрицы, порядка n>3 - C++
Всем доброго времени суток, я достаточно долго искал шаблон кода для вычисления определителя квадратной матрицы, нашел на просторах рунета...

Нахождение определителя - C++
Условие: Вот мой вариант(немного исправил условие под себя): #include &lt;cstdio&gt; #include &lt;conio.h&gt; double Det(double** Mat, int...

Вычисление определителя - C++
Здравствуйте, дорогие форумчане! Помогите, пожалуйста, отладить программу вычисления определителя на Cи++ Текст программы: ...

Нахождение определителя матрицы - C++
Здравствуйте, помогите пожалуйста дописать. Нужно было реализовать в виде модуля, программку, которая выполняет действия над квадратными...

Вычисление определителя матрицы N*N - C++
Дорогие форумчане, никто не подскажет как вычислить определитель квадратной матрицы, сам код не нужен, только алгоритм. Насколько я слышал...

16
edward_jonson
158 / 158 / 25
Регистрация: 23.02.2011
Сообщений: 392
25.08.2012, 18:03 #2
В вашей программе массив имеет тип int, а во второй - double, измените.
1
Nuclear_Razor
49 / 2 / 0
Регистрация: 22.07.2012
Сообщений: 104
Записей в блоге: 1
Завершенные тесты: 1
25.08.2012, 19:10  [ТС] #3
edward_jonson, если поменять в моей программе обьявление массива через тип double, то считает правильно для матриц порядком меньше трех :-(
0
edward_jonson
158 / 158 / 25
Регистрация: 23.02.2011
Сообщений: 392
25.08.2012, 19:37 #4
Nuclear_Razor, а
C++
1
int det=1;
вы заменили на
C++
1
double det=1.0;
в 41-й строке?
и ещё в 12 -
C++
1
scanf("%lf",&a[i][j]);
и 21 -
C++
1
printf("\t%lf",a[i][j]);
?
1
Nuclear_Razor
49 / 2 / 0
Регистрация: 22.07.2012
Сообщений: 104
Записей в блоге: 1
Завершенные тесты: 1
25.08.2012, 19:56  [ТС] #5
edward_jonson, аахахах боже мой! Как я мог ввод упустить! Спасибо! Сейчас проверю!

Добавлено через 13 минут
edward_jonson, определитель считает теперь правильно. Но корни СЛАУ стал выдавать неверно. В чем может быть ошибка?

Код:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
        int  I=0, J=0, check=0, ri=0;
    double a[10][10];
    double rate=0,ratio=0,b[x][x],t;
    bool F;
 
//Проверка на нулевую строку с ненулевым вектором свободных членов данной строки
for(int i=0;i<I;i++)
  {
  for(int j=0;j<J-1;j++)
    if ((a[i][j]==0)&&(a[i][J-1]!=0))
      check++;
  if (check==J-1)
    {
    cout <<"Матрица не совместна.\n";
    
    F=false;
    system("pause"); //Пауза системы
    } 
  check=0;
  }
 
//Проверка на нулевой столбец - система имеет бесконечно много решений на данном столбце
for(int j=0;j<J-1;j++)
  {
  for(int i=0;i<I;i++)
    if (a[i][j]==0)
      check++;
  if (check==I)
    {
    printf("Матрица имеет бесконечно много решений на %d столбце. \n",j+1);
    
    F=false;
    getch();
    char c;
    c = getch();
    if (c==13) exit(0);
 
    system("pause"); //Пауза системы, скушай твикс
    }
  check=0;
  }
 
if (I<J-1)
  {
    printf("Матрица имеет бесконечно много решений, т.к. строк меньше, чем столбцов.\n");
 
    F=false;
    getch();
    char c;
    c = getch();
    if (c==13) exit(0);
  system("pause");//Пауза системы, скушай снигерс
  }
 
//Дублирование проверки
for (int i=0;i<I;i++)
  for(int j=0;j<J;j++)
    b[i][j]=a[i][j]*1.0;
 
for(int col=0;col<J-1;col++)
  {
  for(int i=col;i<I;i++)
    if (b[i][col]!=0)
      {
      rate=b[i][col];
      ri=i;
      break;
      }
  for(int j=0;j<J;j++)
    b[ri][j]/=rate;
  for(int j=0;j<J;j++) //Поднимаем строку с ненулевым элементом наверх на позиции кол
    {
    t=b[col][j];
    b[col][j]=b[ri][j];
    b[ri][j]=t;
    }
  for(int i=0;i<I;i++)
    if (i!=col)
      {
      ratio=b[i][col]/b[col][col];
      for(int j=0;j<J;j++)
        b[i][j]-=ratio*b[col][j];
      }
  }
cout << "Матрица преобразований имеет вид:\n";
gr;
for (int i=0;i<I;i++)
  {
  for(int j=0;j<J;j++)
    
    printf("\t%6.1f",b[i][j]);//Вывод матрицы преобразований
    printf("\n");
    
}
gr;
for(int i=0;i<I;i++)
  {
  for(int j=0;j<J-1;j++)
    if ((b[i][j]==0)&&(b[i][J-1]!=0))
      check++;
  if (check==J-1)
    {
    printf("Матрица не совместна.\n");
    
    F=false;
    getch();
    char c;
    c = getch();
    if (c==13) exit(0);
    system("pause"); //Пауза системы, скушай баунти
    }
  check=0;
  }
 
cout << "\nПолученные решения:\n";
for(int i=0;i<J-1;i++)
  printf("\nx%d = %.3lf\n",i+1,b[i][J-1]);
Я думаю опять что-то с типами данных. Но массив b[i][j] уже изначально был объявлен через double.
0
edward_jonson
158 / 158 / 25
Регистрация: 23.02.2011
Сообщений: 392
25.08.2012, 20:23 #6
Вы уверены, что ваш код для решения СЛАУ методом Гаусса был работоспособен? Если хотите, могу вам скинуть рабочий, переделаете его под себя. Для алгоритма не есть хорошо, что изменение типа данных ставит под вопрос его корректность.
1
Nuclear_Razor
49 / 2 / 0
Регистрация: 22.07.2012
Сообщений: 104
Записей в блоге: 1
Завершенные тесты: 1
25.08.2012, 20:27  [ТС] #7
edward_jonson, да-да конечно! Я проверял матрицы 6x7 и 10x10 и все считалось верно! Но это было до того как я решил усовершенствовать программу, то есть тогда массив а был целочисленный...а теперь они оба double, и видать из-за этого считает все неверно...точнее где-то в сортировке идет неправильный подсчет, т.к. матрицу преобразований уже выводить неправильно. Это очень сильно меня напрягает, потому что программу почти месяц пишу.

А он совсем уж мудреный? Я просто вообще физик , и знаю только самый минимум в C++

Добавлено через 48 секунд
edward_jonson, они - это "а" и "b", второй массив - "b" для проверки и вывода корней нужен.
0
edward_jonson
158 / 158 / 25
Регистрация: 23.02.2011
Сообщений: 392
25.08.2012, 21:17 #8
Я вам к рабочему коду с определителем добавил рабочий код с гауссом, но используя динамические массивы + матрица будет квадратной (для не квадратной искать определитель не получится, да и гаусс будет давать бесконечное кол-во решений, а для вектора свободных членов введен свой одномерный массив). Вам лишь осталось добавить обработку ситуаций, когда нет корней и т.п.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#define EPS 0.000000001
 
int main()
{
    double **A, **Am, *X, *b, mu, t;  // AX = b
    int i, j, n, k, x, y;
 
    printf ("Введите размерность матрицы:\n");
    scanf("%d", &n);
 
    A = (double**)malloc(n * sizeof(double*));
    for (i = 0; i < n; i ++)
        A[i] = (double*)malloc(n * sizeof(double));
    Am = (double**)malloc(n * sizeof(double*));
    for (i = 0; i < n; i ++)
        Am[i] = (double*)malloc(n * sizeof(double));
    X = (double*)malloc(n * sizeof(double));
    b = (double*)malloc(n * sizeof(double));
 
    printf ("Заполните матрицы A i b:\n");
 
    for (i = 0; i < n; i ++) {
        for (j = 0; j < n; j ++) {
            printf ("Введите A[%d][%d]=", i, j);
            scanf ("%lf", &A[i][j]);
            Am[i][j] = A[i][j];
        }
        printf ("Введите b[%d]=", i);
        scanf("%lf", &b[i]);
    }
 
    printf ("Исходная матрица:\n");
    for (i = 0; i < n; i ++) {
        for (j = 0; j < n; j ++)
            printf ("%9.2lf", A[i][j]);
        printf ("\n");
    }
 
    double kk;
 
    for (x = 0; x < (n - 1); x ++) {
        for (y = (x + 1); y < n; y ++) {
            kk =- Am[y][x] / Am[x][x];
            for (j = 0; j < n; j ++) {
                Am[y][j] += kk * Am[x][j];
                if ( fabs(A[y][j] ) < EPS) Am[y][j] = 0;
            }
        }
    }
 
    double det = 1.0;
    for(int i = 0; i < n; i ++)
        det *= Am[i][i];
 
    printf("\nОпределитель = %lf\n", det);
 
    printf ("Метод Гаусса:\n");
    for (k = 0; k < n; k ++)
        for (i = k + 1 ; i < n; i ++) {
            mu = A[i][k] / A[k][k];
            for (j = 0; j < n; j ++)
                A[i][j] -= A[k][j] * mu;
            b[i] -= b[k] * mu;
        }
 
    printf ("Матрица А, приведённая к треугольному виду; матрица b :\n");
    for (i = 0; i < n; i ++) {
        for (j = 0; j < n; j ++)
            printf ("%9.2lf", A[i][j]);
        printf ("%25.2lf", b[i]);
        printf ("\n");
    }
 
    for (i = n - 1; i >= 0; i --) {
        t = b[i];
        for(j = i + 1; j < n; j++)
            t -= A[i][j] * X[j];
        X[i] = t / A[i][i];
    }
 
    printf ("Ответ для метода Гаусса\n");
    for (k = 0; k < n; k ++) printf ("%lf\n", X[k]);
 
    for (i = 0; i < n; i ++) free(A[i]);
    free (A);
 
    for (i = 0; i < n; i ++) free(Am[i]);
    free (Am);
 
    free (X);
    free (b);
    return 0;
}
Код не мудрёный ни разу, только работа с памятью, циклы и арифметические операции.
ЗЫ: возможныая причина появления ошибок у вас - сама матрица изменяется во время нахождения корней и определителя(поэтому нужна резервная матрица), и использование abs вместо fabs для вещественных чисел.
1
Nuclear_Razor
49 / 2 / 0
Регистрация: 22.07.2012
Сообщений: 104
Записей в блоге: 1
Завершенные тесты: 1
25.08.2012, 22:13  [ТС] #9
edward_jonson, посмотрю сейчас и отпишусь в любом случае! У меня программа для широкого круга пользователей, так что все равно придется все расписывать и проверять.

Добавлено через 21 минуту
edward_jonson, отлично), вернулись к моей первоначальной программе. Корни находит правильно, а определитель нет.
0
edward_jonson
158 / 158 / 25
Регистрация: 23.02.2011
Сообщений: 392
25.08.2012, 22:30 #10
Nuclear_Razor, Ну вы приведите пример исходных данных при котором результат неверен. Я для 3-го порядка проверял - всё ок.
0
Nuclear_Razor
49 / 2 / 0
Регистрация: 22.07.2012
Сообщений: 104
Записей в блоге: 1
Завершенные тесты: 1
25.08.2012, 22:43  [ТС] #11
edward_jonson, вот ссылка на пример решения в онлайне:

онлайн решение

Если ввести исходные данные, используя ваш шаблон кода, то программа считает неправильно только определитель.

Ссылка не открывается, вот условие:

Условие
4x 1 + 8x 2 - 5x 3 + 4x 4 = 5
4x 1 +11x 2 +12x 3 + 5x 4 = -9
23x 1 + 3x 2 + 6x 3 + 4x 4 = 11
34x 1 + 2x 2 - 8x 4 = 0

Определитель тут матрицы без столбца свободных членов: -43496

А ваша программа вычисляет такой: -66820
0
edward_jonson
158 / 158 / 25
Регистрация: 23.02.2011
Сообщений: 392
25.08.2012, 22:46 #12
Ссылка не пашет.
0
Nuclear_Razor
49 / 2 / 0
Регистрация: 22.07.2012
Сообщений: 104
Записей в блоге: 1
Завершенные тесты: 1
25.08.2012, 22:47  [ТС] #13
edward_jonson, предыдущий ответ исправил сразу как раз из-за ссылки
0
edward_jonson
158 / 158 / 25
Регистрация: 23.02.2011
Сообщений: 392
25.08.2012, 23:27 #14
Nuclear_Razor, Вот чёрт в строке 49 описка, там массив Am, а не A
Именно: fabs(Am[y][j])
1
Nuclear_Razor
49 / 2 / 0
Регистрация: 22.07.2012
Сообщений: 104
Записей в блоге: 1
Завершенные тесты: 1
25.08.2012, 23:53  [ТС] #15
edward_jonson, Окей! Сейчас исправлю и проведу парочку тестов, в любом случае отпишусь.

Добавлено через 18 минут
edward_jonson, все пока отлично. Правда числа с плавающей запятой неточно вычисляет (погрешности у корней ~ 0,2), а у определителя погрешность ~ 10 единиц. Кстати, что за столбец b, когда матрица приводиться к треугольному виду? Что-то я уже совсем все забыл. В интернете немного порылся, слишком много муры, может вы помните?)
0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
25.08.2012, 23:53
Привет! Вот еще темы с ответами:

Функции (Расчет определителя матрицы) - C++
Задание: Ввести с клавиатуры матрицу 4*4 и подсчитать ее определитель. Процедуру подсчета определителя оформить в виде функции. во я...

Считывание и запись определителя матрицы - C++
в файле записан массив , его надо считать и найти его определитель, и записать его в другой файл. программа не хочет считывать данные. ...

Нахождение детерминанта (определителя) матрицы - C++
У меня вот код есть для нахождения детерминанта (определителя) матрицы 5х5 :) а как сделать, чтобы я мог сам ввести данные матрицы? ...

Вычисление определителя Методом Гаусса - C++
Как сделать обмен строк в этом методе? #include &lt;stdio.h&gt; #include &lt;conio.h&gt; #include &lt;cstdlib&gt; #include &lt;iostream&gt; #include...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Yandex
Объявления
25.08.2012, 23:53
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru