Как написать матрицу в c. Статический массив: объявление, заполнение, использование

Оборудование 10.10.2020
Оборудование

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

— это непрерывный участок памяти, содержащий последовательность объектов одинакового типа, обозначаемый одним именем.

Массив характеризуется следующими основными понятиями:

Элемент массива (значение элемента массива) – значение, хранящееся в определенной ячейке памяти, расположенной в пределах массива, а также адрес этой ячейки памяти.
Каждый элемент массива характеризуется тремя величинами:

  • адресом элемента — адресом начальной ячейки памяти, в которой расположен этот элемент;
  • индексом элемента (порядковым номером элемента в массиве);
  • значением элемента.

Адрес массива – адрес начального элемента массива.

Имя массива – идентификатор, используемый для обращения к элементам массива.

Размер массива – количество элементов массива

Размер элемента – количество байт, занимаемых одним элементом массива.

Графически расположение массива в памяти компьютера можно представить в виде непрерывной ленты адресов.

Представленный на рисунке массив содержит q элементов с индексами от 0 до q-1 . Каждый элемент занимает в памяти компьютера k байт, причем расположение элементов в памяти последовательное.

Адреса i -го элемента массива имеет значение

Адрес массива представляет собой адрес начального (нулевого) элемента массива. Для обращения к элементам массива используется порядковый номер (индекс) элемента, начальное значение которого равно 0 . Так, если массив содержит q элементов, то индексы элементов массива меняются в пределах от 0 до q-1 .

Длина массива – количество байт, отводимое в памяти для хранения всех элементов массива.

ДлинаМассива = РазмерЭлемента * КоличествоЭлементов

Для определения размера элемента массива может использоваться функция

int sizeof (тип);

Например,

sizeof (char ) = 1;
sizeof (int ) = 4;
sizeof (float ) = 4;
sizeof (double ) = 8;

Объявление и инициализация массивов

Для объявления массива в языке Си используется следующий синтаксис:

тип имя[размерность]={инициализация};

Инициализация представляет собой набор начальных значений элементов массива, указанных в фигурных скобках, и разделенных запятыми.

int a = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; // массив a из 10 целых чисел

Если количество инициализирующих значений, указанных в фигурных скобках, меньше, чем количество элементов массива, указанное в квадратных скобках, то все оставшиеся элементы в массиве (для которых не хватило инициализирующих значений) будут равны нулю. Это свойство удобно использовать для задания нулевых значений всем элементам массива.

int b = {0}; // массив b из 10 элементов, инициализированных 0


Если массив проинициализирован при объявлении, то константные начальные значения его элементов указываются через запятую в фигурных скобках. В этом случае количество элементов в квадратных скобках может быть опущено.

int a = {1, 2, 3, 4, 5, 6, 7, 8, 9};

При обращении к элементам массива индекс требуемого элемента указывается в квадратных скобках .

Пример на Си

1
2
3
4
5
6
7
8

#include
int main()
{
int a = { 5, 4, 3, 2, 1 }; // массив a содержит 5 элементов
printf("%d %d %d %d %d\n" , a, a, a, a, a);
getchar();
return 0;
}

Результат выполнения программы:

Однако часто требуется задавать значения элементов массива в процессе выполнения программы. При этом используется объявление массива без инициализации. В таком случае указание количества элементов в квадратных скобках обязательно.

int a;

Для задания начальных значений элементов массива очень часто используется параметрический цикл:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18


#include
int main()
{
int a;
int i;
// Ввод элементов массива
for (i = 0; i<5; i++)
{
printf("a[%d] = " , i);
scanf("%d" , &a[i]);
}
// Вывод элементов массива
for (i = 0; i<5; i++)
printf("%d " , a[i]); // пробел в формате печати обязателен
getchar(); getchar();
return 0;
}

Результат выполнения программы

Многомерные массивы

В языке Си могут быть также объявлены многомерные массивы. Отличие многомерного массива от одномерного состоит в том, что в одномерном массиве положение элемента определяется одним индексом, а в многомерном - несколькими. Примером многомерного массива является матрица.

Общая форма объявления многомерного массива

тип имя[размерность1][размерность2]...[размерностьm];

Элементы многомерного массива располагаются в последовательных ячейках оперативной памяти по возрастанию адресов. В памяти компьютера элементы многомерного массива располагаются подряд, например массив, имеющий 2 строки и 3 столбца,

int a;


будет расположен в памяти следующим образом

Общее количество элементов в приведенном двумерном массиве определится как

КоличествоСтрок * КоличествоСтолбцов = 2 * 3 = 6.

Количество байт памяти, требуемых для размещения массива, определится как

КоличествоЭлементов * РазмерЭлемента = 6 * 4 = 24 байта.

Инициализация многомерных массивов

Значения элементов многомерного массива, как и в одномерном случае, могут быть заданы константными значениями при объявлении, заключенными в фигурные скобки {} . Однако в этом случае указание количества элементов в строках и столбцах должно быть обязательно указано в квадратных скобках .

Пример на Си

1
2
3
4
5
6
7
8
9

#include
int main()
{
int a = { 1, 2, 3, 4, 5, 6 };
printf("%d %d %d\n" , a, a, a);
getchar();
return 0;
}



Однако чаще требуется вводить значения элементов многомерного массива в процессе выполнения программы. С этой целью удобно использовать вложенный параметрический цикл .

Пример на Си

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

#define _CRT_SECURE_NO_WARNINGS
#include
int main()
{
int a; // массив из 2 строк и 3 столбцов
int i, j;
// Ввод элементов массива
for (i = 0; i<2; i++) // цикл по строкам
{
for (j = 0; j<3; j++) // цикл по столбцам
{
printf("a[%d][%d] = " , i, j);
scanf("%d" , &a[i][j]);
}
}
// Вывод элементов массива
for (i = 0; i<2; i++) // цикл по строкам
{
for (j = 0; j<3; j++) // цикл по столбцам
{
printf("%d " , a[i][j]);
}
printf("\n" ); // перевод на новую строку
}
getchar(); getchar();
return 0;
}



Передача массива в функцию

Обработку массивов удобно организовывать с помощью специальных функций. Для обработки массива в качестве аргументов функции необходимо передать

  • адрес массива,
  • размер массива.

Исключение составляют функции обработки строк, в которые достаточно передать только адрес.

При передаче переменные в качестве аргументов функции данные передаются как копии. Это означает, что если внутри функции произойдет изменение значения параметра, то это никак не повлияет на его значение внутри вызывающей функции.

Если в функцию передается адрес переменной (или адрес массива), то все операции, выполняемые в функции с данными, находящимися в пределах видимости указанного адреса, производятся над оригиналом данных, поэтому исходный массив (или значение переменной) может быть изменено вызываемой функцией.

Пример на Си Дан массив из 10 элементов. Поменять местами наибольший и начальный элементы массива. Для операций поиска максимального элемента и обмена использовать функцию.

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

#define _CRT_SECURE_NO_WARNINGS
#include
// Функция обмена
void change(int *x, int n)
{
// x - указатель на массив (адрес массива)
// n - размер массива
int i;
int max, index;
max = x;
index = 0;
// Поиск максимального элемента
for (i = 1; i {
if (x[i]>max)
{
max = x[i];
index = i;
}
}
// Обмен
x = x;
x = max;
}
// Главная функция
int main()
{
int a;
int i;
for (i = 0; i<10; i++)
{
printf("a[%d] = " , i);
scanf("%d" , &a[i]);
}
change(a, 10); // вызов функции обмена
// Вывод элементов массива
for (i = 0; i<10; i++)
printf("%d " , a[i]);
getchar();
getchar();
return
p = p * x[i];
}
return p;
}
// Главная функция
int main()
{
int a; // объявлен массив a из 5 элементов
int i;
int pr;
// Ввод элементов массива
for (i = 0; i<5; i++)
{
printf("a[%d] = " , i);
scanf("%d" , &a[i]); // &a[i] - адрес i-го элемента массива
}
pr = func(a, 5); // вычисление произведения
printf("\n pr = %d" , pr); // вывод произведения четных элементов
getchar(); getchar();
return 0;
}



Безусловно, по входным данным можно восстановить матрицы, тривиальным образом их перемножить и вывести результат в заданном виде. Как пример плохого стиля программирования: наивный алгоритм приводит к почти двукратному перерасходу потребляемой памяти и существенно уступает в производительности. Существует другое решение, прийти к которому можно путем последовательного приспособления стандартных матричных операций к формату входных данных.

Наибольшую сложность, как вычислительную, так и идейную, представляет умножение матриц, в данном случае — возведение в квадрат. Нижеприведенная последовательность шагов позволит перемножать симметричные матрицы, используя их линейное представление в формате исходных данных.

Замечание 1

Подпространство симметричных матриц незамкнуто относительно умножения: произведением двух симметричных матриц может быть несимметричная матрица.

Пример

\left(\begin{array}{ccc} 1 & 1 & 3 \\ 1 & 4 & 5 \\ 3 & 5 & 0\end{array} \right) \cdot \left(\begin{array}{ccc} 4 & 0 & 0 \\ 0 & 4 & 3 \\ 0 & 3 & 2 \end{array} \right) = \left(\begin{array}{ccc} 4 & 13 & 9 \\ 4 & 31 & 22 \\ 12 & 20 & 15 \end{array} \right)

Замечание 2

Степень симметрической матрицы также является симметрической матрицей. Доказательство основано на представлении матрицы как представления линейного оператора и на свойствах эрмитовых операторов.

Во всех дальнейших выкладках подразумевается, что матрица представлена линейным массивом из \frac{n(n+1)}{2} элементов.

Для начала, заметим, что элемент c_{i,j} матрицы C=A^{2}, равен скалярному произведению (как векторов в стандартном базисе) i-ой строки матрицы A на j-ую её строку (в силу того, что в симметричной матрице j-ая строка совпадает с j-м столбцом). Следовательно, для возведения в степень симметричной матрицы необходимо и достаточно реализовать операцию скалярного перемножения двух её строк.

Тогда следует понять, как по данному представлению матрицы получить её i-ую строку. Для удобства, выпишем имеющиеся элементы в виде полной матрицы. Заметим, что первым элементом i-ой строки будет i-ый элемент первой строки, и обобщим это наблюдение. Обозначим позицию текущего интересующего нас элемента i-ой строки как j. Если j < i, то следует выбрать i-ый элемент j-ой строки, иначе следует выбрать все элементы j-ой строки, лежащие правее данного. Графически можно интерпретировать алгоритм таким образом: начиная с i-го элемента первой строки, спускаться вертикально вниз по матрице до тех пор, пока не будет достигнута i-ая строка, далее — двигаться вправо до конца строки. Наглядность алгоритма позволяет легко воплотить его программно.
Следует только пронаблюдать, как изменяются расстояния между элементами, лежащими один под другим, при движении вниз по строкам матрицы, что позволит легко перенести алгоритм на линейное представление верхней треугольной матрицы. Предлагаем читателю самому проделать это несложное, но наглядное упражнение, для лучшего понимания алгоритма.

Теперь можно перейти непосредственно к реализации.

До этого момента, мы рассматривали только одномерные массивы, то есть, к элементу массива мы обращались через один индекс. Однако, массивы могут быть и двумерными и трехмерными и, даже, n-мерными. Многомерные массивы — это массивы, у которых есть более одного индекса. Вместо одной строки элементов, многомерные массивы можно рассматривать как совокупность элементов, которые распределены по двум или более измерениям. Вот так, например, можно визуализировать двумерный массив:

В этом примере изображен двумерный массив размером 3*5, 3 — строки и 5 столбцов. Объявление двумерного массива почти ничем не отличается от объявления одномерного, за исключением того, что при объявлении двумерного массива, нужно указывать размер каждого измерения в квадратных скобочках. Например, давайте объявим двумерный массив размером 8*8, это размер поля для стандартных шашек — 8 строк и 8 столбцов:

Int checkers; // двумерный массив

То есть, двумерный массив хорошо подходит для хранения информации на шашечном поле. Также двумерный массив можно легко использовать для хранения информации о любой другой игре — шахматы, крестики нолики, сапер и т. д. Чтобы получить доступ к любому элементу такого массива, нужно воспользоваться двумя значениями — индексами, первый индекс — это номер строки, а второй — номер столбца. Все выше сказанное относится и к n-мерным массивам. Хотя, уже 4-х мерные массивы сложновато визуализировать. Присваивать значения элементам массива очень просто, вот пример:

// присваиваем первому элементу массива значение - 5 myArray = 5;

Пример присваивания значения элемента двумерного массива:

// присваиваем первому элементу массива значение - 5 myArray = 10;

В этом примере мы присвоили значение 10 элементу двумерного массива myArray , который находится во второй строке и в 4-м столбце. Визуально это выглядит так:

[__][__][__][__][__] [__][__][__][__] [__][__][__][__][__]

Как видите, все просто, главное помните, что нумерация строк и столбцов всегда начинается с 0. То есть, я еще раз хочу вам напомнить, что вы никогда не должны пытаться записать данные после последнего элемента массива, например, когда у вас есть массив размером — 10 элементов и вы пытаетесь присвоить значение элементу с индексом . Память для массива была выделена только для десяти элементов, (индексы от 0 до 9), поэтому элемента с индексом 10 просто не существует. В таком случае, запись в оперативной памяти может привести к непредсказуемым последствиям — например, вы можете в конечном итоге испортить работу параллельно запущенной программы. Однако, как правило, операционная система не позволит такого рода безрассудное поведение и приведет к краху программы, если та попытается получить доступ к нераспределенной памяти.

Давайте рассмотрим практический пример использования массивов в программах:

#include int main() { int i, j; int myArray; // объявляем массив размером 8*8 элементов for (i = 0; i < 8; i++) { for (j = 0; j < 8; j++) myArray[i][j] = i * j; // каждому элементу присваиваем значение произведения текущих индексов элемента массива } printf("Вот такой массив у нас получился:\n"); for (i = 0; i < 8; i++) { for (j = 0; j < 8; j++) { printf("[%d][%d]=%d ", i, j, myArray[i][j]); } printf("\n"); } getchar(); }

Сразу смотрим результат работы программы:

Вот такой массив у нас получился: =0 =0 =0 =0 =0 =0 =0 =0 =0 =1 =2 =3 =4 =5 =6 =7 =0 =2 =4 =6 =8 =10 =12 =14 =0 =3 =6 =9 =12 =15 =18 =21 =0 =4 =8 =12 =16 =20 =24 =28 =0 =5 =10 =15 =20 =25 =30 =35 =0 =6 =12 =18 =24 =30 =36 =42 =0 =7 =14 =21 =28 =35 =42 =49

В этом примере, мы сначала заполняем двумерный массив произведением его индексов, строки 8 — 11 . А потом выводим на экран его содержимое, строки 13 — 20 .

Если вы хотите объявить указатель на массив, то вы не должны использовать операцию взятия адреса — & , вот пример:

Char *ptrArray; char myString; ptrArray = myString; // указателю присваиваем адрес первого элемента массива myString без использования &

В то время как с обычными переменными, этого сделать нельзя, пример:

Int *ptrNumber; int number; ptrNumber = &number; // обязательно используем оператор - &

На первый взгляд, тот факт, что массивы работают как указатели, может запутать вас, но это специфика языка программирования, это нужно просто запомнить.

P.S.: После прочтения статьи, рекомендую вам отвлечься от программирования. Хороший способ это сделать — интересная игра. Достаньте смартфон и запустите свою любимую игру. А вот и полезная ссылка для фанатов андроида — скачать игры для андроид . Игр очень много и все интересные, а главное — бесплатные.

I . На кого рассчитан модуль.

Данный модуль рассчитан учащегося в старшей школе или студента. Должны быть освоены такие темы как работа с циклами, с указателями, необходимо знать, что такое одномерный массив.

II . Мотивация

Мы уже знаем, для чего нам могут понадобиться одномерные массивы. Например, мы можем сохранить в одномерном массиве коэффициенты квадратного уравнения и посчитать корни, используя дискриминант. А если нам нужно посчитать много таких уравнений? Неужели каждый раз перезаписывать новые коэффициенты на место старых? А если необходимо будет вернуться к уже посчитанным? Или нам нужно решить систему из нескольких уравнений, т.е. нужно одновременно работать со всеми? Если нам просто нужно хранить таблицу каких-то значений, например, измерений при опыте, как нам это сделать, используя полученные уже знания?

Для каждого из вышеназванных случаев можно просто объявить несколько одномерных массивов, но вот приятно ли будет работать с таким количеством? Ведь каждый нужно будет назвать и обработать отдельно. Ситуация похожа на ту, когда мы только вводили понятие одномерного массива. Тут и приходят на помощь массивы двумерные.

III. Изложение материала модуля

Обычным представлением таких массивов являются таблицы значений, содержащие информацию в строках и столбцах. Чтобы определить отдельный табличный элемент, нужно указать два индекса: первый (по соглашению) указывает номер строки, а второй (опять же по соглашению) указывает номер столбца.

Рисунок иллюстрирует двумерный массив a . Массив содержит три строки и четыре столбца, так что, еще говорят, - это массив три на четыре. Вообще, массивы с m строками и n столбцами называют массивами m на n .

Каждый элемент в массиве а определяется именем элемента в форме a [ i ][ j ]; a это имя массива, а i и j – индексы, которые однозначно определяют каждый элемент в а . Заметим, что имена элементов первой строки имеют первый индекс 0 , имена элементов в четвертом столбце имеют второй индекс 3 .

Типичная ошибка программирования

Неправильная ссылка на элемент двумерного массива a [ x ] [ y ] как a [ x , y ]. На самом деле, a [ x , y ] воспринимается как a [ y ] , потому что С оценивает выражение (содержащее операцию последования - запятую) x , y просто как y (последнее из разделенных запятыми выражений).

Многомерные массивы могут получать начальные значения в своих объявлениях точно так же, как массивы с естественным индексом. Например, двумерный массив b можно объявить и дать ему начальные значения таким образом:

int b = {{1,2}, {3,4}};

Значения группируются в строки, заключенные в фигурные скобки. Таким образом, элементы b иb получают начальныезначения 1 и 2, а элементы b и b получают начальные значения 3 и 4. Если начальных значений в данной строчке не хватает для их присвоения всем элементам строки, то остающимся элементам присваиваются нулевые начальные значения. Таким образом, объявление

int b = {{1,},{3,4}};

будет означать, что b получает начальное значение 1, b получает начальное значение 0.

Объем памяти в байтах, занимаемый двухмерным массивом, вычисляется по следующей формуле:

Количество байтов = размер_1-го_измерения*размер_2-го_измерения*sizeof(базовый тип)

Например, двумерный массив 4-байтовых целых чисел размерностью 10*5 занимает участок памяти объемом

то есть 200 байтов.

Передача массива в функцию.

Рассмотрим небольшую программу вывода элементов двумерного массива:

#include

void printArray(int a)

for (int i = 0; i<=1;i++)

for (int j=0; j<=2; j++)

printf(“%i, ”,&a[i][j]);

printf(“\n”);

int array = {{1,2,3},{4,5,6}};

printf(“Values in array on rows:”);

printgArray(array);

Values in array on rows:

Программа вызывает функцию printArray для вывода элементов массива. Заметим, что описание функции указывает параметр – массив как int a . Когда мы задаем как аргумент функции одномерный массив, скобки в списке параметров функции пусты. Размерность первого индекса многомерного массива также не требуется, но все последующие размерности индексов необходимы. Компилятор использует размерности этих индексов для определения соответствующих ячеек памяти для доступа к элементам многомерных массивов. В памяти все элементы массива хранятся последовательно, независимо от количества индексов (размерности массива). В двумерном массиве первая строка хранится в памяти перед второй строкой.

Наличие размерностей индексов в объявлении параметра дает возможность компилятору сообщить функции о том, как расположены элементы в массиве. В двумерном массиве каждая строка является одномерным массивом. Чтобы определить местоположение элемента в некоторой строке, функция должна точно знать, сколько элементов находится в каждой строке. Тогда функция может пропустить соответствующее количество ячеек памяти при обращении к массиву. Таким образом, при обращении к a функция знает, что для доступа ко второй строке (строка 1) нужно пропустить в памяти три элемента первой строки, а затем обратиться к третьему элементу этой строки (элементу 2).

Многие типовые операции с массивами используют конструкцию for . Так, следующий цикл определяет сумму всех элементов массива a :

for (row = 0; row < 3; row++)

for (column = 0; column < 3; column ++)

total += a ;

Внутренняя структура for суммирует элементы одной строки массива. Внешняя структура for начинает работу с установки row (т.е. индекса строки) в нуль, так что во внутренней структуре for могут быть просуммированы элементы второй строки. Далее внешняя структура for увеличивает row до значения 2, так что могут быть просуммированы элементы третьей строки. После завершения работы вложенной структурыfor печатается результат.

Задача

Учащиеся одного из ВУЗов как-то поспорили, у кого наивысший средний бал за только что сданную сессию. Заодно захотели выяснить, кто получил наилучшую и наихудшую оценки. Для интереса представим, что мы живем в Америке, и оценки выставляются по 100-бальной шкале.

Указание:

Программа должна «знать» имена студентов, выводить их на экран. То же самое с таблицей успеваемости. Подразумевается, что номера столбцов эквивалентны номерам экзаменов.

Размышления о решении задачи

Для начала давайте определимся, что нам нужно для решения этой задачи. Первое, на что мы обращаем внимание – это то, что в условие явно сказано слово «таблица». Значит, скорее всего, для работы с ней мы будем использовать двумерный массив. Каждая строка в нем – это успеваемость отдельного студента. Как и сказано в условии, номер столбца будет определять номер сданного экзамена, номер строки – студента. Именно с этим массивом мы и будем работать, вычисляя средний бал, минимум и максимум. Видно, что необходимо будет создать три функции для получения нужных нам данных и функцию вывода таблицы оценок на экран. Все, что нужно для написания этой части программы, мы уже знаем.

Теперь разберемся с именами. Неплохо было бы их скомпоновать в таблицу, для того, чтобы по номеру студента можно было определить его имя и наоборот. Мы уже знаем. Что строка – это одномерный массив символов. Значит, можно создать двумерный массив, в котором номер строки будет определять номер студента, а номер столбца – соответствующую букву имени. Но тогда придется создать массив с наибольшим количеством ячеек по горизонтали из возможных. Т.е., если у нас есть четыре студента:

То необходимо будет создать таблицу, подобную изображенной на рисунке:


Серым цветом на рисунке показаны пустые клетки нашего массива. На эти клетки будет отведено место в памяти, но вот пользоваться они не будут. Так зачем они нам нужны? Нет ли способа избежать такой ситуации? Оказывается, есть. Об этом будет рассказано ниже, а затем мы вернемся к решению нашей задачи.

Вообще-то программировать расчёт определителей не нужно. Их умеет считать, скажем, встроенная функция МОПРЕД из Excel:

  • набираем элементы матрицы в смежных ячейках, например, матрица размерностью 4*4 показана на картинке;
  • в нужной ячейке вводим формулу (в нашем случае =МОПРЕД(A1:D4) и нажимаем Enter:)

Не труднее вычислить и в MathCAD - просто нажать кнопку на панели матриц...

Но иногда нужен алгоритм, а не ответ... вот немного кода на консольном C++, на совершенство он не претендует, но нули в матрице или "не тот" порядок элементов смущать функцию determinant не должны. Пример из main - 1001-й на работу с динамической матрицей средствами C++ :) Остальное закомментировано в исходнике.

#define bool int #define true 1 #define false 0 int search (double **a, int m, int n, double what, bool match, unsigned int &uI, unsigned int &uJ, unsigned int starti, unsigned int startj) { // Поиск в матрице a[m][n] элемента с указанным значением what // Возвращаеются его номер строки и столбца uI, uJ, если элемент найден. // match - искать равный элемент или отличный от указанного. // Вернёт 0 - не найдено, не 0 - найдено if ((!m) || (!n)) return 0; if ((starti >= n) || (startj >= m)) return 0; for (unsigned int i = starti; i < n; i++) for (unsigned int j = startj; j < m; j++) { if (match == true) { if (a[i][i] == what) { uI = i; uJ = j; return 1; } } else if (a[i][j] != what) { uI = i; uJ = j; return 1; } } return 0; } void swaprows (double **a, int n, int m, unsigned int x1, unsigned int x2) { //Меняет в матрице a[n][m] строки с номерами x1 и x2 местами if ((!n) || (!m)) return; if ((x1 >= n) || (x2 >= n) || (x1 == x2)) return; double tmp; for (unsigned int x = 0; x < m; x++) { tmp = a[x]; a[x] = a[x]; a[x] = tmp; } return; }; void swapcolumns (double **a, int n, int m, unsigned int x1, unsigned int x2) { //Меняет в матрице a[n][m] столбцы с номерами x1 и x2 местами if ((!n) || (!m)) return; if ((x1 >= m) || (x2 >= m) || (x1 == x2)) return; double tmp; for (unsigned int x = 0; x < n; x++) { tmp = a[x]; a[x] = a[x]; a[x] = tmp; } return; }; double determinant (double **a, unsigned int n) { //Вычисление определителя квадратной матрицы a[n][n] unsigned int m = n; if (m == 0) return 0; if (m == 1) return a; if (m == 2) return (a * a - a * a); bool sign = false; // смена знака определителя. по умолчанию - нет double det = 1; // определитель double tmp; unsigned int x, y; for (unsigned int i = 0; i < n; i++) { // цикл по всей главной диагонали if (a[i][i] == 0) { // если элемент на диагонали равен 0, то ищем ненулевой элемент в матрице if (!search(a,m,n,0, false, y, x, i, i)) return 0; // если все элементы нулевые, то опр. = 0 if (i != y) { // меняем i-ую строку с y-ой swaprows(a,m,n,i, y); sign = !sign; } if (i != x) { // меняем i-ый столбец с x-ым swapcolumns(a,m,n,i, x); sign = !sign; } // таким образом, в a[i][i], теперь ненулевой элемент. } // выносим элемент a[i][i] за определитель det *= a[i][i]; tmp = a[i][i]; for (x = i; x < m; x++) { a[i][x] = a[i][x] / tmp; } // таким образом a[i][i] теперь равен 1 // зануляем все элементы стоящие под (i, i)-ым, // при помощи вычитания с опр. коеффициентом for (y = i + 1; y < n; y++) { tmp = a[y][i]; for (x = i; x < m; x++) a[y][x] -= (a[i][x]*tmp); } } if (sign) return det*(-1); return det; }; #include int main () { const int n=4; int data = { 5,4,3,2, 11,-1,2,7, 0,1,0,4, -13,79,1,2 }; int i,j,k=0; double **a = new double * [n]; for (i=0; i

Рекомендуем почитать

Наверх