4×4 матрицы умножения


Это простой C++ код с функцией mult для умножения матриц. Это может легко быть обобщена для любого \$Н \Время Н\$ матрицы путем замены 4 С любое положительное число больше 1.

Умножение делается с помощью перебора строк, и итерации (вложенные в строки итерации) над столбцами. В то время как внутри итерации столбцов, умножение выполняется, что является скалярное произведение (опять же, используя новую итерацию).

Простой пример показывает умножение \долларов \раз\$.

Я интересно, если есть лучшие способы в написании этой.

Код:

#include <iostream>
#include <string>

using namespace std;

int mult(int A[4][4], int B[4][4]){

int C[4][4], num;

for (int i=0; i<4; i++){
     for(int j=0; j<4; j++){
        num = 0;
        for(int k=0; k<4; k++){
          num += A[i][k]*B[k][j];
}
      C[i][j]=num; 
      cout << num << " ";
}
     cout << endl;
}

return 0;

}

int main(){

   int A[4][4], ind=0;
cout << "Default Matrix A: \n \n";

   for (int i=0; i<4; i++){
     for(int j=0; j<4; j++){
      A[i][j]=ind; ind++;
      cout<< A[i][j]<< " ";
}
     cout << endl;


}
    cout << "\nMultiplication of A^2: \n \n";
mult(A,A);
return 0;

}

Выход:

Default Matrix A:

    0 1 2 3
    4 5 6 7
    8 9 10 11
    12 13 14 15

Multiplication of A^2:

56 62 68 74
152 174 196 218
248 286 324 362
344 398 452 506


4675
5
задан 4 февраля 2018 в 11:02 Источник Поделиться
Комментарии
1 ответ

Избежать using namespace std

Это может вызвать конфликты имен, так как каждое имя в std пространство имен глобальное пространство имен. Для небольшой программы, как это маловероятно, что вы столкнетесь с проблемами (опять же, может и нет) но это лучше, чтобы получить в привычку использовать std:: префикс имен в std пространства имен.

Кроме того, вы можете ввести с помощью объявлений как using std::cout; чтобы добавить конкретные имена в глобальное пространство имен.

Избежать std::endl в пользу \n

std::endl сбрасывает поток, что может привести к потере производительности.

Объявлять переменные в самой местные возможности

Вы объявляете num в начале mult() но вы на самом деле не использовать его (и инициализировать его в 0), пока вы находитесь внутри j петли. Лучше просто объявить и инициализировать его в том же месте и в том месте, где вы начинаете использовать его.

Я бы также переименовать его, чтобы быть более описательным (например, sum или dot_product).

Избегайте жестко цифр

Ваш код работает с \$4\4 раза\$ матриц, но у вас есть 4 жестко всех на место. Вы говорите


Это может легко быть обобщена для любой матрицы n х N, заменив 4 С любое положительное число больше 1.

Но есть много случаев, когда 4 должен быть заменен. Как минимум, вы должны определить 4 как константу и использовать эту константу в коде:

const std::size_t N = 4; // or constexpr instead of const if your compiler supports it

int mult(int A[N][N], int B[N][N]) {
int C[N][N];

for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
int num = 0;
for (int k = 0; k < N; k++) {
num += A[i][k] * B[k][j];
}
C[i][j] = num;
std::cout << num << " ";
}
std::cout << std::endl;
}

return 0;
}

Теперь я просто нужно изменить определение N после использования ряда других, чем 4.

Использовать static_assert чтобы обеспечить условие, что \$Н > 1\$

Если ваш компилятор поддерживает static_assert вы можете гарантировать, что \$П > 1\$ во время компиляции и вызвать компиляция неудачи с простым сообщением, чтобы объяснить проблему.

Шаблон функции

Алгоритм умножения практически одинакова для любого \$П > 1\$, так что эта функция является хорошим кандидатом для шаблона функции, основанные на измерении \Н$\$. Например, у вас есть A С N = 4но в той же программе вы можете получать матрицу (2Д массив) D С N = 3 и тот же код используется для умножения с обеих матрицах. Вот демо с помощью шаблона функции:

#include <iostream>
#include <string>

template<std::size_t N>
int mult(int A[N][N], int B[N][N]) {
static_assert(N > 1, "N must be greater than 1");

int C[N][N];

for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
int num = 0;
for (int k = 0; k < N; k++) {
num += A[i][k] * B[k][j];
}
C[i][j] = num;
std::cout << num << " ";
}
std::cout << std::endl;
}

return 0;
}

int main() {
const std::size_t N = 4;
int A[N][N];
int ind = 0;
std::cout << "Default Matrix A: \n \n";

for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
A[i][j] = ind; ind++;
std::cout << A[i][j] << " ";
}
std::cout << std::endl;
}
std::cout << "\nMultiplication of A^2: \n \n";
mult<N>(A, A);

const std::size_t N2 = 3;
int D[N2][N2];
ind = 0;
std::cout << "\nDefault Matrix D: \n \n";

for (int i = 0; i < N2; i++) {
for (int j = 0; j < N2; j++) {
D[i][j] = ind; ind++;
std::cout << D[i][j] << " ";
}
std::cout << std::endl;
}
std::cout << "\nMultiplication of D^2: \n \n";
mult<N2>(D, D);
return 0;
}

Рассмотрим Matrix класс вместо 2D массивов

Математические библиотеки реализуют матриц как класса. Внутренне Matrix класс может использовать 2D массивов для хранения данных, но клиентский код не должен зависеть от того, как эти данные хранятся. А Matrix класса можно скрыть детали реализации от клиентского кода.

Распространяется на неквадратных матриц

В общем, \$П \раз\$ матрица \долл\$ можно умножить матрицу \$Ъ$ если \$б\ долларов \$М \раз Р\$ (\$А\ долл \$м\$ столбцов и \$Б\ долл \$м\$ строк, но в остальном две матрицы могут иметь разные размеры). С помощью шаблона функции вы можете легко расширить функции умножение неквадратных матриц. Просто добавьте нужный шаблон Аргументы и подправить алгоритм, чтобы использовать другие размеры, чем N. Вот демо:

#include <iostream>
#include <string>

template<std::size_t N, std::size_t M, std::size_t P>
int mult(int A[N][M], int B[M][P]) {
static_assert(N > 1, "N must be greater than 1");
static_assert(M > 1, "M must be greater than 1");
static_assert(P > 1, "P must be greater than 1");

int C[N][P];

for (int n = 0; n < N; n++) {
for (int p = 0; p < P; p++) {
int num = 0;
for (int m = 0; m < M; m++) {
num += A[n][m] * B[m][p];
}
C[n][p] = num;
std::cout << num << " ";
}
std::cout << std::endl;
}

return 0;
}

int main() {
int A[4][3]{
{1, 2, 3},
{4, 5, 6},
{7, 8, 9},
{10, 11, 12}
};

int B[3][2]{
{1, 2},
{3, 4},
{5, 6}
};

mult<4, 3, 2>(A, B);
return 0;
}

Демо-программа выводит \$П \раз Р\$ (\$4 \2 раза\$) матрица продукта:

22 28
49 64
76 100
103 136

9
ответ дан 5 февраля 2018 в 05:02 Источник Поделиться