Я собираюсь немного оспорить структуру вопроса: вы не используете правильный тип «двумерного массива» в качестве структуры данных.
В C у вас есть возможностьвызовите вашу функцию с гибкими границами массива.Это позволяет вашим массивам быть прямоугольными , то есть строками одинакового размера, расположенными непрерывно в памяти.Одна простая реализация:
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
void sq_matrix_mul( const ptrdiff_t n,
const double left[n][n],
const double right[n][n],
double product[n][n] )
{
for ( ptrdiff_t i = 0; i < n; ++i )
for ( ptrdiff_t j = 0; j < n; ++j ) {
product[i][j] = 0.0;
for ( ptrdiff_t k = 0; k < n; ++k )
product[i][j] += left[i][k] * right[k][j];
} // end for j
}
#define DIMENSION 4
int main(void)
{
static const double a[DIMENSION][DIMENSION] = {
{ 1, 0, 0, 0 },
{ 0, 2, 0, 0 },
{ 0, 0, 3, 0 },
{ 0, 0, 0, 4 }
};
static const double b[DIMENSION][DIMENSION] = {
{ 1, 1, 1, 1 },
{ 1, 1, 1, 1 },
{ 1, 1, 1, 1 },
{ 1, 1, 1, 1 }
};
double c[DIMENSION][DIMENSION];
sq_matrix_mul( DIMENSION, a, b, c );
for ( ptrdiff_t i = 0; i < DIMENSION; ++i ) {
fputs( "[ ", stdout );
for ( ptrdiff_t j = 0; j < DIMENSION; ++j )
printf( "%f ", c[i][j] );
fputs( "]\n", stdout );
}
return EXIT_SUCCESS;
}
Конечно, есть более сложные алгоритмы умножения массива с лучшим временем выполнения, чем O (N³).
Поскольку элементы прямоугольного массива непрерывны в памятиЕсли вы буквально хотите увеличивать их (например, чтобы установить для каждого элемента матрицы одно и то же значение), вы просто инициализируете указатель на первый элемент и увеличиваете его.
Используемая вами структура данных,double**
, является рваный массив .Это почти никогда не та структура данных, которую вы действительно хотите (к сожалению, все программисты на C и C ++ сначала узнают о char** argv
).Рваные массивы требуют динамического выделения для каждой строки, а не одного для всей матрицы, добавляют поиск указателя для доступа и имеют плохую локальность данных, что делает их намного медленнее.Они также тратят память на все эти указатели.
Если ваш массив разрежен, существуют более эффективные структуры данных, такие как сжатая разреженная строка.Если он плотный и все строки имеют одинаковый размер, прямоугольный массив строго превосходит рваный массив.
Если вы хотите придерживаться рваного массива, просто используйте прототип функции, который вы сделалидо и держать цикл таким же.Индексы массива, такие как a[i][k]
, будут работать для рваного или прямоугольного массива.
Мое личное предпочтение состоит в том, чтобы использовать ptrdiff_t
(тип, который вы получаете при вычитании указателей) для индексов массива, поскольку они подписаныи не создавайте столько ошибок от тихих переполнений и продвижений типов, сколько делают беззнаковые типы.Они также имеют правильную ширину, не ограниченную 32 битами в 64-битных системах.
Наконец, в C ++ это решение будет недопустимым;Я обычно пишу класс двумерного массива для обеспечения абстракции с нулевой стоимостью.