Matrix Operations: Programs in C, C++, Java, and Python
Matrix addition, subtraction, and multiplication programs in C, C++, Java, and Python, with dimension rules, verified worked examples, and time complexity analysis.
Matrix addition, subtraction, and multiplication each follow a different rule about which inputs are valid, and that rule determines everything that follows.
Get the rule wrong and the operation is undefined. Get it right and the rest is iteration: loop over indices, apply the arithmetic, fill the result. This article lays out the rules, walks through verified worked examples, and gives complete programs in C, C++, Java, and Python for all three operations.
Dimension Rules That Govern All Three Operations
Every matrix operation starts with a validity check. Confirming dimensions before writing a loop saves debugging time and avoids the most common mistake beginners make.
Addition and subtraction both require that the two input matrices have exactly the same number of rows and the same number of columns. If matrix A is m×n and matrix B is also m×n, the operation is valid and the result is another m×n matrix.
Multiplication has an asymmetric rule. If A is m×n, then B must have exactly n rows (it can have any number of columns p). The product A×B is valid and the result is m×p. The shared inner dimension n disappears in the output; only the outer dimensions m and p survive.
A quick visual check: write the two dimension pairs side by side. For multiplication, the inner pair must match.
- (2×3)(3×2): inner pair is (3, 3), they match, result is 2×2. Valid.
- (3×4)(4×5): inner pair is (4, 4), they match, result is 3×5. Valid.
- (2×3)(2×4): inner pair is (3, 2), they do not match. Undefined.
For addition and subtraction, both dimension pairs must be identical.
- (2×3) + (2×3): identical, valid. Result is 2×3.
- (2×3) + (3×2): dimensions differ, undefined.
These rules are not optional edge cases. They are the definition of the operations. Any code that skips the dimension check will produce garbage output on mismatched inputs without any runtime error in languages like C.
Matrix Addition and Subtraction
Both operations are element-wise: for each position (i, j), compute a[i][j] + b[i][j] or a[i][j] - b[i][j] and write the result to result[i][j]. Two nested loops cover all positions.
Worked Example
Using two 2×3 matrices:
- A = [[1, 2, 3], [4, 5, 6]]
- B = [[6, 5, 4], [3, 2, 1]]
Addition steps:
- result[0][0] = 1 + 6 = 7
- result[0][1] = 2 + 5 = 7
- result[0][2] = 3 + 4 = 7
- result[1][0] = 4 + 3 = 7
- result[1][1] = 5 + 2 = 7
- result[1][2] = 6 + 1 = 7
- Addition result: [[7, 7, 7], [7, 7, 7]]
Subtraction steps:
- result[0][0] = 1 - 6 = -5
- result[0][1] = 2 - 5 = -3
- result[0][2] = 3 - 4 = -1
- result[1][0] = 4 - 3 = 1
- result[1][1] = 5 - 2 = 3
- result[1][2] = 6 - 1 = 5
- Subtraction result: [[-5, -3, -1], [1, 3, 5]]
C Program
In C, 2D array parameters require a known column size in the function signature. The example below fixes the column size at 3 to match the worked example.
#include <stdio.h>
void addMat(int rows, int cols, int a[][3], int b[][3], int r[][3]) {
int i, j;
for (i = 0; i < rows; i++)
for (j = 0; j < cols; j++)
r[i][j] = a[i][j] + b[i][j];
}
void subMat(int rows, int cols, int a[][3], int b[][3], int r[][3]) {
int i, j;
for (i = 0; i < rows; i++)
for (j = 0; j < cols; j++)
r[i][j] = a[i][j] - b[i][j];
}
void printMat(int rows, int cols, int mat[][3]) {
int i, j;
for (i = 0; i < rows; i++) {
for (j = 0; j < cols; j++)
printf("%4d", mat[i][j]);
printf("\n");
}
}
int main(void) {
int a[2][3] = {{1, 2, 3}, {4, 5, 6}};
int b[2][3] = {{6, 5, 4}, {3, 2, 1}};
int addR[2][3], subR[2][3];
addMat(2, 3, a, b, addR);
printf("Addition:\n");
printMat(2, 3, addR);
subMat(2, 3, a, b, subR);
printf("Subtraction:\n");
printMat(2, 3, subR);
return 0;
}
Output:
Addition:
7 7 7
7 7 7
Subtraction:
-5 -3 -1
1 3 5
C++ Program
C++ vectors remove the fixed-column-size constraint. The Matrix alias keeps the function signatures readable.
#include <iostream>
#include <vector>
using namespace std;
using Matrix = vector<vector<int>>;
Matrix add(const Matrix& a, const Matrix& b) {
int rows = a.size(), cols = a[0].size();
Matrix result(rows, vector<int>(cols));
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
result[i][j] = a[i][j] + b[i][j];
return result;
}
Matrix subtract(const Matrix& a, const Matrix& b) {
int rows = a.size(), cols = a[0].size();
Matrix result(rows, vector<int>(cols));
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
result[i][j] = a[i][j] - b[i][j];
return result;
}
void printMatrix(const Matrix& m) {
for (const auto& row : m) {
for (int val : row)
cout << val << " ";
cout << "\n";
}
}
int main() {
Matrix a = {{1, 2, 3}, {4, 5, 6}};
Matrix b = {{6, 5, 4}, {3, 2, 1}};
cout << "Addition:\n"; printMatrix(add(a, b));
cout << "Subtraction:\n"; printMatrix(subtract(a, b));
return 0;
}
Java Program
Java’s 2D arrays are arrays of arrays. The a.length gives row count; a[0].length gives column count without any fixed-size constraint.
public class MatrixAddSub {
static int[][] add(int[][] a, int[][] b) {
int rows = a.length, cols = a[0].length;
int[][] result = new int[rows][cols];
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
result[i][j] = a[i][j] + b[i][j];
return result;
}
static int[][] subtract(int[][] a, int[][] b) {
int rows = a.length, cols = a[0].length;
int[][] result = new int[rows][cols];
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
result[i][j] = a[i][j] - b[i][j];
return result;
}
static void print(int[][] mat) {
for (int[] row : mat) {
for (int v : row) System.out.print(v + " ");
System.out.println();
}
}
public static void main(String[] args) {
int[][] a = {{1, 2, 3}, {4, 5, 6}};
int[][] b = {{6, 5, 4}, {3, 2, 1}};
System.out.println("Addition:"); print(add(a, b));
System.out.println("Subtraction:"); print(subtract(a, b));
}
}
Python Program
Python’s list comprehension form is the most concise. The explicit nested-loop version below mirrors the C and Java structure for easier cross-language comparison.
def add_matrices(a, b):
rows, cols = len(a), len(a[0])
result = [[0] * cols for _ in range(rows)]
for i in range(rows):
for j in range(cols):
result[i][j] = a[i][j] + b[i][j]
return result
def subtract_matrices(a, b):
rows, cols = len(a), len(a[0])
result = [[0] * cols for _ in range(rows)]
for i in range(rows):
for j in range(cols):
result[i][j] = a[i][j] - b[i][j]
return result
def print_matrix(mat):
for row in mat:
print(' '.join(str(v) for v in row))
a = [[1, 2, 3], [4, 5, 6]]
b = [[6, 5, 4], [3, 2, 1]]
print("Addition:")
print_matrix(add_matrices(a, b))
print("Subtraction:")
print_matrix(subtract_matrices(a, b))
Matrix Multiplication
Multiplication is fundamentally different from addition. The operation is not element-wise. Each output element is the dot product of a row from the first matrix with a column from the second matrix.
For a result matrix R = A×B where A is m×n and B is n×p:
R[i][j]= sum ofA[i][k] * B[k][j]for k from 0 to n-1- Row index i comes from A, column index j comes from B, the shared index k iterates across n positions
This produces three nested loops: an outer loop over i (rows of A), a middle loop over j (columns of B), and an inner loop over k (the shared dimension). The inner loop accumulates the dot product for one output cell before moving to the next.
Worked Example
Multiply A (2×3) by B (3×2). Inner dimensions both equal 3, so the product is valid. Result size is 2×2.
- A = [[1, 2, 3], [4, 5, 6]]
- B = [[7, 8], [9, 10], [11, 12]]
Computing each element of the 2×2 result:
- result[0][0] = (1×7) + (2×9) + (3×11) = 7 + 18 + 33 = 58
- result[0][1] = (1×8) + (2×10) + (3×12) = 8 + 20 + 36 = 64
- result[1][0] = (4×7) + (5×9) + (6×11) = 28 + 45 + 66 = 139
- result[1][1] = (4×8) + (5×10) + (6×12) = 32 + 50 + 72 = 154
- Multiplication result: [[58, 64], [139, 154]]
C Program
#include <stdio.h>
/* Multiply A (2x3) by B (3x2) to get result (2x2) */
void mulMat(int a[2][3], int b[3][2], int r[2][2]) {
int i, j, k;
for (i = 0; i < 2; i++)
for (j = 0; j < 2; j++) {
r[i][j] = 0;
for (k = 0; k < 3; k++)
r[i][j] += a[i][k] * b[k][j];
}
}
int main(void) {
int a[2][3] = {{1, 2, 3}, {4, 5, 6}};
int b[3][2] = {{7, 8}, {9, 10}, {11, 12}};
int r[2][2];
int i, j;
mulMat(a, b, r);
printf("Multiplication (2x3 times 3x2):\n");
for (i = 0; i < 2; i++) {
for (j = 0; j < 2; j++)
printf("%4d", r[i][j]);
printf("\n");
}
return 0;
}
Output:
58 64
139 154
C++ Program
The vector-based implementation generalises to any m×n and n×p input.
#include <iostream>
#include <vector>
using namespace std;
using Matrix = vector<vector<int>>;
Matrix multiply(const Matrix& a, const Matrix& b) {
int m = a.size(), n = a[0].size(), p = b[0].size();
Matrix result(m, vector<int>(p, 0));
for (int i = 0; i < m; i++)
for (int j = 0; j < p; j++)
for (int k = 0; k < n; k++)
result[i][j] += a[i][k] * b[k][j];
return result;
}
void printMatrix(const Matrix& mat) {
for (const auto& row : mat) {
for (int v : row) cout << v << " ";
cout << "\n";
}
}
int main() {
Matrix a = {{1, 2, 3}, {4, 5, 6}};
Matrix b = {{7, 8}, {9, 10}, {11, 12}};
cout << "Multiplication (2x3 times 3x2):\n";
printMatrix(multiply(a, b));
return 0;
}
Java Program
public class MatrixMultiply {
static int[][] multiply(int[][] a, int[][] b) {
int m = a.length, n = a[0].length, p = b[0].length;
int[][] result = new int[m][p];
for (int i = 0; i < m; i++)
for (int j = 0; j < p; j++)
for (int k = 0; k < n; k++)
result[i][j] += a[i][k] * b[k][j];
return result;
}
static void print(int[][] mat) {
for (int[] row : mat) {
for (int v : row) System.out.print(v + " ");
System.out.println();
}
}
public static void main(String[] args) {
int[][] a = {{1, 2, 3}, {4, 5, 6}};
int[][] b = {{7, 8}, {9, 10}, {11, 12}};
System.out.println("Multiplication:");
print(multiply(a, b));
}
}
Python Program
def multiply_matrices(a, b):
m, n, p = len(a), len(a[0]), len(b[0])
result = [[0] * p for _ in range(m)]
for i in range(m):
for j in range(p):
for k in range(n):
result[i][j] += a[i][k] * b[k][j]
return result
def print_matrix(mat):
for row in mat:
print(' '.join(str(v) for v in row))
a = [[1, 2, 3], [4, 5, 6]]
b = [[7, 8], [9, 10], [11, 12]]
print("Multiplication (2x3 times 3x2):")
print_matrix(multiply_matrices(a, b))
# Output: 58 64
# 139 154
Time and Space Complexity
The three loops in matrix multiplication directly map to the time complexity. The outer loop runs m times (rows of A), the middle loop runs p times (columns of B), and the inner loop runs n times (the shared dimension). Each iteration does one multiplication and one addition. Total work: O(m×n×p).
For the space analysis, the relevant reference is space complexity of algorithms, which covers the standard framework. Applied to matrix operations, only the output allocation counts as extra space:
| Operation | Input dimensions | Time complexity | Output space |
|---|---|---|---|
| Addition | m×n + m×n | O(m×n) | O(m×n) |
| Subtraction | m×n - m×n | O(m×n) | O(m×n) |
| Multiplication | m×n × n×p | O(m×n×p) | O(m×p) |
For square n×n matrices, addition and subtraction are O(n²) time and space; multiplication is O(n³) time and O(n²) space. The output matrix is n×n regardless of the inner dimension used during computation.
Naive O(n³) multiplication is the expected answer in placement coding tests. Academic research on faster matrix multiplication exists: Strassen’s algorithm runs in roughly O(n^2.807), but it carries large constant factors and adds implementation complexity that placement test scope does not require.
Matrix Operations in Placement Coding Rounds
Matrix questions in Indian placement tests tend to cluster into three forms.
The first is a straight implementation: write a function to multiply two matrices given as 2D arrays. The expected answer is the triple-loop structure shown above. The examiner may ask you to handle general m×n and n×p inputs, not just square matrices, so the generalised version from the C++ or Java section above is the safer answer.
The second form is a bug-detection question. A code snippet multiplies a 3×4 matrix by a 4×3 matrix but declares the result as a 4×4 array. Identify the error. The result of a 3×4 times 4×3 multiplication is 3×3, not 4×4, so the result array is oversized. A trickier variant gives two matrices with incompatible dimensions and asks you to detect the mismatch before any calculation starts.
The third form is complexity analysis: state the time complexity of multiplying an m×n matrix by an n×p matrix. The expected answer is O(m×n×p), with an explanation of which loop accounts for each variable.
For related 2D-traversal problems that appear alongside matrix questions in the same coding round, see find all symmetric pairs in an array and equilibrium index of an array for the underlying iteration patterns.
Every large language model runs its attention mechanism as a sequence of matrix multiplications: the same O(m×n×p) triple-loop structure from the code above, applied to matrices with dimensions in the millions and executed on GPU hardware. TinkerLLM at ₹299 is the entry point to interact with those models directly and start building applications on top of them, without needing to implement the GPU kernels yourself.
Primary sources
Frequently asked questions
What are the dimension rules for matrix multiplication?
Matrix A (m×n) can only be multiplied by matrix B (n×p): B's row count must equal A's column count. The result is an m×p matrix. If A is 3×4 and B is 4×5, the result is 3×5. If A is 3×4 and B is 3×5, multiplication is undefined because the inner dimensions 4 and 3 do not match.
Is matrix multiplication commutative?
No. In general, A×B is not equal to B×A. Even for square matrices of the same size, the products differ. With A=[[1,2],[3,4]] and B=[[5,6],[7,8]], A×B=[[19,22],[43,50]] but B×A=[[23,34],[31,46]]. Order always matters in matrix multiplication.
How do I multiply a 3×2 matrix by a 2×4 matrix?
A 3×2 matrix has 2 columns and a 2×4 matrix has 2 rows, so the inner dimensions match and multiplication is valid. The result is a 3×4 matrix. Each element result[i][j] is the dot product of row i from the 3×2 matrix with column j from the 2×4 matrix.
What is the time complexity of naive matrix multiplication?
O(m×n×p) where A is m×n and B is n×p. For two n×n square matrices this is O(n cubed). The three nested loops — one for result rows, one for result columns, one for the dot-product sum — each run n iterations in the square case, giving n×n×n total operations.
Can I add matrices with different sizes?
No. Matrix addition and subtraction require both matrices to have exactly the same number of rows and the same number of columns. Adding a 2×3 matrix to a 3×2 matrix is undefined — the shapes do not align element-wise and the operation simply does not exist.
Why does matrix multiplication take O(m×n×p) time but O(m×p) space?
Time is O(m×n×p) because the triple nested loop iterates m×p result positions and each position requires n multiply-and-add steps. Space is O(m×p) because only the output matrix is new allocation — the input matrices A and B are read-only and are not counted as extra space.
A self-paced playground for building with LLMs.
TinkerLLM is FACE Prep's sister property. A guided environment for shipping real LLM applications, the kind of project that earns a paragraph on your resume, not a line.
Try TinkerLLM (₹299 launch)