Mastering Matrix Operations in C: From Basics to Advanced Applications

目次

1. Why Learn Matrices in C Language

The Importance of Learning Matrices in C

Learning how to work with matrices in C language is not only a way to improve your programming skills but also an important step toward expanding your range of applications.

What is a Matrix?

A matrix is a mathematical structure that arranges numbers in a grid, consisting of rows and columns. For example:

| 1  2  3 |
| 4  5  6 |
| 7  8  9 |

This example shows a 3×3 matrix. Matrices are widely used in the following fields:

  • Graphics: Rotating and scaling 3D objects.
  • Machine Learning: Vector calculations and matrix operations on data.
  • Physics Simulations: Modeling system states.

Why Use C Language for Matrices

C language excels in performance and flexibility, making it suitable for large-scale data and low-level computations. Learning matrix operations in C provides the following skills:

  1. Understanding Memory Management: Flexible data handling with dynamic memory allocation.
  2. Building Efficient Algorithms: Calculation methods using nested loops and arrays.
  3. Practical Applications: Scientific computing, image processing, and machine learning.

This article provides a systematic guide from the basics to advanced applications.

2. Matrix Basics and Representation in C

Basic Concepts of Matrices

As a foundation for working with matrices, it is important to understand their structure and the basic operations they support:

  • Scalar Multiplication: Multiplying all elements of a matrix by a constant value.
  • Addition & Subtraction: Adding or subtracting corresponding elements.
  • Multiplication: Calculating the matrix product (with specific rules).
  • Transpose: Swapping rows and columns.

How to Represent Matrices in C

In C, matrices are typically represented using two-dimensional arrays.

Declaring a Static Matrix

If the matrix size is known in advance, you can use a 2D array as follows:

#include <stdio.h>

int main() {
    int matrix[3][3] = {
        {1, 2, 3},
        {4, 5, 6},
        {7, 8, 9}
    };

    printf("matrix[1][1] = %d\n", matrix[1][1]);  // Output: 5
    return 0;
}

This example declares a 3×3 matrix and initializes its elements.

Using Dynamic Memory Allocation

When you need a matrix with a size determined at runtime, you can use malloc to allocate memory:

#include <stdio.h>
#include <stdlib.h>

int main() {
    int rows = 3, cols = 3;
    int **matrix = (int **)malloc(rows * sizeof(int *));
    for (int i = 0; i < rows; i++) {
        matrix[i] = (int *)malloc(cols * sizeof(int));
    }

    // Assign values
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            matrix[i][j] = i * cols + j + 1; // Values from 1 to 9
        }
    }

    // Print matrix
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            printf("%d ", matrix[i][j]);
        }
        printf("\n");
    }

    // Free memory
    for (int i = 0; i < rows; i++) {
        free(matrix[i]);
    }
    free(matrix);

    return 0;
}

This method allows you to decide the matrix size dynamically, providing more flexibility in operations.

侍エンジニア塾

3. How to Perform Matrix Operations in C

Matrix Addition and Subtraction

Matrix addition and subtraction are simple operations where corresponding elements are added or subtracted.

Example: Matrix Addition

The following program adds two matrices of the same size:

#include <stdio.h>

#define ROWS 2
#define COLS 3

void addMatrices(int matrix1[ROWS][COLS], int matrix2[ROWS][COLS], int result[ROWS][COLS]) {
    for (int i = 0; i < ROWS; i++) {
        for (int j = 0; j < COLS; j++) {
            result[i][j] = matrix1[i][j] + matrix2[i][j];
        }
    }
}

int main() {
    int matrix1[ROWS][COLS] = {{1, 2, 3}, {4, 5, 6}};
    int matrix2[ROWS][COLS] = {{6, 5, 4}, {3, 2, 1}};
    int result[ROWS][COLS];

    addMatrices(matrix1, matrix2, result);

    printf("Addition Result:\n");
    for (int i = 0; i < ROWS; i++) {
        for (int j = 0; j < COLS; j++) {
            printf("%d ", result[i][j]);
        }
        printf("\n");
    }

    return 0;
}

Example: Matrix Subtraction

The process is almost the same as addition — just replace + with -.

Matrix Multiplication

Matrix multiplication is slightly more complex, involving multiplying rows of the first matrix by columns of the second matrix.

Example: Matrix Multiplication

The following example multiplies a 2×3 matrix with a 3×2 matrix to produce a 2×2 matrix:

#include <stdio.h>

#define ROWS1 2
#define COLS1 3
#define ROWS2 3
#define COLS2 2

void multiplyMatrices(int matrix1[ROWS1][COLS1], int matrix2[ROWS2][COLS2], int result[ROWS1][COLS2]) {
    for (int i = 0; i < ROWS1; i++) {
        for (int j = 0; j < COLS2; j++) {
            result[i][j] = 0;
            for (int k = 0; k < COLS1; k++) {
                result[i][j] += matrix1[i][k] * matrix2[k][j];
            }
        }
    }
}

int main() {
    int matrix1[ROWS1][COLS1] = {{1, 2, 3}, {4, 5, 6}};
    int matrix2[ROWS2][COLS2] = {{1, 2}, {3, 4}, {5, 6}};
    int result[ROWS1][COLS2];

    multiplyMatrices(matrix1, matrix2, result);

    printf("Multiplication Result:\n");
    for (int i = 0; i < ROWS1; i++) {
        for (int j = 0; j < COLS2; j++) {
            printf("%d ", result[i][j]);
        }
        printf("\n");
    }

    return 0;
}

Matrix Transpose

Transposing a matrix means swapping its rows and columns.

Example: Matrix Transpose

#include <stdio.h>

#define ROWS 2
#define COLS 3

void transposeMatrix(int matrix[ROWS][COLS], int transposed[COLS][ROWS]) {
    for (int i = 0; i < ROWS; i++) {
        for (int j = 0; j < COLS; j++) {
            transposed[j][i] = matrix[i][j];
        }
    }
}

int main() {
    int matrix[ROWS][COLS] = {{1, 2, 3}, {4, 5, 6}};
    int transposed[COLS][ROWS];

    transposeMatrix(matrix, transposed);

    printf("Transposed Matrix:\n");
    for (int i = 0; i < COLS; i++) {
        for (int j = 0; j < ROWS; j++) {
            printf("%d ", transposed[i][j]);
        }
        printf("\n");
    }

    return 0;
}

The transpose operation produces a new matrix by switching the rows and columns of the original matrix.

4. Advanced Matrix Operations and Practical Examples

Calculating the Inverse Matrix

An inverse matrix is one that, when multiplied by the original matrix, produces the identity matrix. However, not all matrices have an inverse — it exists only if the matrix is “non-singular” (its determinant is not zero).

Example: Inverse of a 2×2 Matrix

The following program calculates the inverse of a 2×2 matrix:

#include <stdio.h>

void calculateInverse(int matrix[2][2], float inverse[2][2]) {
    int determinant = matrix[0][0] * matrix[1][1] - matrix[0][1] * matrix[1][0];
    if (determinant == 0) {
        printf("The inverse matrix does not exist.\n");
        return;
    }

    inverse[0][0] = (float)matrix[1][1] / determinant;
    inverse[0][1] = (float)-matrix[0][1] / determinant;
    inverse[1][0] = (float)-matrix[1][0] / determinant;
    inverse[1][1] = (float)matrix[0][0] / determinant;
}

int main() {
    int matrix[2][2] = {{4, 7}, {2, 6}};
    float inverse[2][2];

    calculateInverse(matrix, inverse);

    printf("Inverse Matrix:\n");
    for (int i = 0; i < 2; i++) {
        for (int j = 0; j < 2; j++) {
            printf("%.2f ", inverse[i][j]);
        }
        printf("\n");
    }

    return 0;
}

This program calculates the determinant and then derives the inverse. For 2×2 matrices, this method is straightforward and effective.

Scalar Multiplication and Scaling

Scalar multiplication is the operation of multiplying every element in a matrix by a constant value. This is often used for data normalization or scaling.

Example: Scalar Multiplication

#include <stdio.h>

void scaleMatrix(int rows, int cols, int matrix[rows][cols], int scalar) {
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            matrix[i][j] *= scalar;
        }
    }
}

int main() {
    int matrix[2][3] = {{1, 2, 3}, {4, 5, 6}};
    int scalar = 3;

    scaleMatrix(2, 3, matrix, scalar);

    printf("Scalar Multiplication Result:\n");
    for (int i = 0; i < 2; i++) {
        for (int j = 0; j < 3; j++) {
            printf("%d ", matrix[i][j]);
        }
        printf("\n");
    }

    return 0;
}

By applying scalar multiplication, you can scale the entire matrix at once.

Practical Example: Matrix Operations with User Input

Here is an example program that uses dynamic memory allocation to allow the user to specify the matrix size and perform operations accordingly.

Example: User-Input Matrix Operations

#include <stdio.h>
#include <stdlib.h>

void addMatrices(int rows, int cols, int **matrix1, int **matrix2, int **result) {
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            result[i][j] = matrix1[i][j] + matrix2[i][j];
        }
    }
}

int main() {
    int rows, cols;
    printf("Enter the number of rows: ");
    scanf("%d", &rows);
    printf("Enter the number of columns: ");
    scanf("%d", &cols);

    // Memory allocation
    int **matrix1 = (int **)malloc(rows * sizeof(int *));
    int **matrix2 = (int **)malloc(rows * sizeof(int *));
    int **result = (int **)malloc(rows * sizeof(int *));
    for (int i = 0; i < rows; i++) {
        matrix1[i] = (int *)malloc(cols * sizeof(int));
        matrix2[i] = (int *)malloc(cols * sizeof(int));
        result[i] = (int *)malloc(cols * sizeof(int));
    }

    // Input matrix values
    printf("Enter the first matrix:\n");
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            scanf("%d", &matrix1[i][j]);
        }
    }

    printf("Enter the second matrix:\n");
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            scanf("%d", &matrix2[i][j]);
        }
    }

    // Matrix addition
    addMatrices(rows, cols, matrix1, matrix2, result);

    printf("Addition Result:\n");
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            printf("%d ", result[i][j]);
        }
        printf("\n");
    }

    // Free memory
    for (int i = 0; i < rows; i++) {
        free(matrix1[i]);
        free(matrix2[i]);
        free(result[i]);
    }
    free(matrix1);
    free(matrix2);
    free(result);

    return 0;
}

This program allows the user to define the matrix size and elements, and then dynamically calculates the sum.

5. Applied Programs Using Matrices in C

Image Processing: Grayscale Conversion

In image processing, pixel color data is often stored as matrices. Here is a simple example of converting an RGB image to grayscale.

Example: RGB to Grayscale Conversion

#include <stdio.h>

#define ROWS 3
#define COLS 3

void convertToGrayscale(int red[ROWS][COLS], int green[ROWS][COLS], int blue[ROWS][COLS], int grayscale[ROWS][COLS]) {
    for (int i = 0; i < ROWS; i++) {
        for (int j = 0; j < COLS; j++) {
            // Grayscale conversion using average method
            grayscale[i][j] = (red[i][j] + green[i][j] + blue[i][j]) / 3;
        }
    }
}

int main() {
    int red[ROWS][COLS] = {{255, 128, 64}, {64, 128, 255}, {0, 0, 0}};
    int green[ROWS][COLS] = {{64, 128, 255}, {255, 128, 64}, {0, 0, 0}};
    int blue[ROWS][COLS] = {{0, 0, 0}, {64, 128, 255}, {255, 128, 64}};
    int grayscale[ROWS][COLS];

    convertToGrayscale(red, green, blue, grayscale);

    printf("Grayscale Image:\n");
    for (int i = 0; i < ROWS; i++) {
        for (int j = 0; j < COLS; j++) {
            printf("%d ", grayscale[i][j]);
        }
        printf("\n");
    }

    return 0;
}

This program takes RGB data as input and calculates the corresponding grayscale values. Grayscale images are useful when simplifying image data.

Coordinate Transformation: Rotation Matrix

A rotation matrix is used in graphics and physics simulations to rotate objects in 2D or 3D space.

Example: 2D Coordinate Rotation

This program rotates a point in 2D space by a given angle.

#include <stdio.h>
#include <math.h>

#define PI 3.14159265

void rotatePoint(float x, float y, float angle, float *newX, float *newY) {
    float radians = angle * PI / 180.0;
    *newX = x * cos(radians) - y * sin(radians);
    *newY = x * sin(radians) + y * cos(radians);
}

int main() {
    float x = 1.0, y = 0.0; // Initial coordinates
    float angle = 90.0; // Rotation angle
    float newX, newY;

    rotatePoint(x, y, angle, &newX, &newY);

    printf("Before rotation: (%.2f, %.2f)\n", x, y);
    printf("After rotation: (%.2f, %.2f)\n", newX, newY);

    return 0;
}

This program rotates the point (1, 0) by 90 degrees. The concept of rotation matrices is fundamental in 2D/3D graphics.

Data Analysis: Normalizing a Matrix

In data analysis, scaling a dataset to a specific range is important. Here is an implementation for normalizing a matrix.

Example: Matrix Normalization

#include <stdio.h>

#define ROWS 2
#define COLS 3

void normalizeMatrix(int rows, int cols, int matrix[rows][cols], float normalized[rows][cols]) {
    int max = matrix[0][0], min = matrix[0][0];

    // Find max and min
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            if (matrix[i][j] > max) max = matrix[i][j];
            if (matrix[i][j] < min) min = matrix[i][j];
        }
    }

    // Normalize
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            normalized[i][j] = (float)(matrix[i][j] - min) / (max - min);
        }
    }
}

int main() {
    int matrix[ROWS][COLS] = {{1, 2, 3}, {4, 5, 6}};
    float normalized[ROWS][COLS];

    normalizeMatrix(ROWS, COLS, matrix, normalized);

    printf("Normalized Matrix:\n");
    for (int i = 0; i < ROWS; i++) {
        for (int j = 0; j < COLS; j++) {
            printf("%.2f ", normalized[i][j]);
        }
        printf("\n");
    }

    return 0;
}

This program scales matrix elements to a range of 0–1. Normalization is frequently used in data analysis and machine learning.

6. Further Learning and Applications of Matrix Operations

Using Specialized Libraries

While implementing matrix operations manually is essential for learning, using libraries can greatly improve efficiency for large-scale projects.

Eigen Library

  • Features: A high-performance linear algebra library for C++.
  • Main Functions:
  • Basic operations such as addition, subtraction, multiplication, transpose, and inverse.
  • Advanced features like eigenvalue computation and least squares methods.
  • Official Website: Eigen Official Page

GSL (GNU Scientific Library)

  • Features: A scientific computing library for C.
  • Main Functions:
  • Matrix operations, statistical calculations, and numerical analysis.
  • Simple API design that easily integrates into C programs.
  • Official Website: GSL Official Page

BLAS (Basic Linear Algebra Subprograms)

  • Features: A high-performance library for linear algebra computations.
  • Main Functions:
  • Optimized vector and matrix operations.
  • Commonly used in applications requiring intensive numerical computation.
  • Official Website: Netlib BLAS

Advanced Topics

Once you understand the basics of matrix operations, you can explore the following topics to gain more advanced skills:

1. Processing Large-Scale Matrices

  • Handling matrices with tens of thousands of rows and columns requires efficient algorithms and distributed computing.
  • Related Topics: Matrix decomposition (LU, QR), sparse matrix processing.

2. Numerical Linear Algebra

  • Advanced mathematical processing using matrices.
  • Examples: Eigenvalue/eigenvector computation, solving matrix equations.

3. Applications in Machine Learning and Data Analysis

  • Matrices serve as the fundamental structure for machine learning algorithms.
  • Examples:
  • Dimensionality reduction using Singular Value Decomposition (SVD).
  • Matrix calculations in gradient descent optimization.

Recommended Learning Approach

To master matrix operations, the following approach is recommended:

  1. Review the Basics
  • Practice implementing basic operations (addition, subtraction, transpose, multiplication) repeatedly.
  • Solve matrix problems manually to understand the algorithms deeply.
  1. Create Applied Programs
  • Implement simple image processing programs or coordinate transformations in 2D games.
  • Solving practical problems helps you systematically learn matrix operations.
  1. Contribute to Open-Source Projects
  • Participating in projects that use matrix operations will sharpen your skills to a professional level.
年収訴求