矩阵乘法 - C

Posted

技术标签:

【中文标题】矩阵乘法 - C【英文标题】:Matrix Multiplication - C 【发布时间】:2016-10-14 18:44:08 【问题描述】:

我创建了一个执行矩阵加法、减法和乘法的程序。我已经处理了加法和减法部分,但是当我达到乘法时,我无法输出正确的值。下面我只放了乘法函数的代码。

#define _CRT_SECURE_NO_WARNINGS

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

typedef struct 

int *elements;
int rows;
int columns;

 matrix;

void main() 

        matrix a, b, c;

        void read_matrix(matrix *);
        void deallocate(matrix *);
        void print(matrix);
        matrix add(matrix, matrix);
        matrix subtract(matrix, matrix);
        matrix multiply(matrix, matrix);

        read_matrix(&a);
        read_matrix(&b);
        /*
        c = add(a, b);
        printf("The answer of Matrix (a + b) is \n\n");
        print(a);
        printf("\n  +\n\n");
        print(b);
        printf("\n  =\n\n");
        print(c);
        printf("\n");

        deallocate(&c);
        c = subtract(a, b);
        printf("The answer of Matrix (a - b) is \n\n");
        print(a);
        printf("\n  -\n\n");
        print(b);
        printf("\n  =\n\n");
        print(c);
        printf("\n");

        deallocate(&c);
        */
        c = multiply(a, b);
        printf("The answer of Matrix (a * b) is \n\n");
        print(a);
        printf("\n  *\n\n");
        print(b);
        printf("\n  =\n\n");
        print(c);
        printf("\n");

 

 void read_matrix(matrix *z) 

        int d1, d2, allc, i, x, y, j, val;
        int res;

        printf("\nWhat is the first dimension of the array? ");
        res = scanf("%d", &d1);

        if (res != 1) 
            fprintf(stderr, "Something went wrong with your first dimension!");
                    return;
        

        printf("What is the second dimension of the array? ");
        res = scanf("%d", &d2);
        if (res != 1) 
            fprintf(stderr, "Something went wrong with your second dimension!");
            return;
        

        printf("Matrix Dimension is %dx%d\n", d1, d2);

        allc = d1*d2;

        (*z).elements = (int *)calloc(allc, sizeof(int));
        (*z).rows = d1;
        (*z).columns = d2;

        x = 0;
        j = 0;

        printf("\n");

        for (i = 0; i < d1; i++) 

             x++;

            for (y = 0; y < d2; y++) 
                printf("Enter the value for row %d column %d: ", x, y + 1);
                res = scanf("%d", &val);
                if (res != 1) 
                    fprintf(stderr, "Something went wrong while reading value %d\n", x);
                    return;
                

                (*z).elements[j++] = val;
            

        
    

    void deallocate(matrix *c) 

        free((*c).elements);
        (*c).elements = NULL;
        (*c).rows = 0;
        (*c).columns = 0;
    

    void print(matrix z) 

         int i, j, x;
         x = 0;

        for (i = 0; i < z.rows; i++) 

            printf("[  ");

            for (j = 0; j < z.columns; j++) 

                printf("%-4d", z.elements[x++]);
            
            printf("]\n");
        
    

    matrix multiply(matrix a, matrix b) 

        matrix c;

        int a1, a2, b1, b2, allc, i, j, x, y, z, alc, addval, val;

        i = 0;
        j = 0;
        alc = 0;
        val = 0;
        addval = 0;

        a1 = a.rows;
        a2 = a.columns;
        b1 = b.rows;
        b2 = b.columns;

        allc = (a1 * b2);

        c.elements = (int *)calloc(allc, sizeof(int));
        c.columns = a1;
        c.rows = b2;

        if (a2 != b1) 
            printf("\n\nThe inner dimensions of your matrices do not match! Multiplication cannot be done!\n\n");
            exit(1);
        


        for (x = 0; x < c.rows; x++) 

            for (y = 0; y < c.rows; y++) 

                for (z = 0; z < c.rows; z++) 

                    i = (i * c.rows);

                    addval = (a.elements[j]) * (b.elements[i]);

                    val += addval;

                    j++;
                    i++;
                
                c.elements[alc] = val;
                printf("VAL IS: %d\n\n", val);

                val = 0;

                i = 0;
                alc++;
            
        

        printf("\n\n");

        return c;
    

在乘法函数中,三重嵌套 for 循环应该经过足够多的时间来打印出新数组维度的正确项数。我知道如何进行矩阵乘法,但我不确定我是否在这里正确表示了它。

一个例子的输出是:

What is the first dimension of the array? 3
What is the second dimension of the array? 3
Matrix Dimension is 3x3

Enter the value for row 1 column 1: 1
Enter the value for row 1 column 2: 2
Enter the value for row 1 column 3: 3
Enter the value for row 2 column 1: 4
Enter the value for row 2 column 2: 5
Enter the value for row 2 column 3: 6
Enter the value for row 3 column 1: 7
Enter the value for row 3 column 2: 8
Enter the value for row 3 column 3: 9

What is the first dimension of the array? 3
What is the second dimension of the array? 3
Matrix Dimension is 3x3

Enter the value for row 1 column 1: 1
Enter the value for row 1 column 2: 2
Enter the value for row 1 column 3: 3
Enter the value for row 2 column 1: 4
Enter the value for row 2 column 2: 5
Enter the value for row 2 column 3: 6
Enter the value for row 3 column 1: 7
Enter the value for row 3 column 2: 8
Enter the value for row 3 column 3: 9


The answer of Matrix (a * b) is

[  1   2   3   ]
[  4   5   6   ]
[  7   8   9   ]

  *

[  1   2   3   ]
[  4   5   6   ]
[  7   8   9   ]

  =

[  216847534336951265054271]
[  1641572693-138635672036124672]
[  1352368309-50514195286739134]

Press any key to continue . . .

【问题讨论】:

x、y 和 z 都在计算行数。我希望其中至少有一个应该是计数列。并且i 乘以c.rows,然后在每次通过循环时递增。使用printf 打印i 的值,你会发现它根本不是你想要的。 题外话:在print 函数中,我会将"%-4d" 更改为"%-3d "。当一些数字超过三位数时,这将防止数字聚集在一起。 【参考方案1】:

以下是我对您进行矩阵乘法的代码的修改。问题出在您的 multiply() 函数上。您可以看到它注定要通过增加变量j 来遍历a 矩阵 - 在一个工作解决方案中,矩阵a 的每个元素都会多次参与乘法。

我还将您的例程更改为所有传递指向矩阵结构的指针,而不是直接按值传递指针和传递/返回矩阵结构的混合。我认为这更加一致且更易于遵循,但这意味着如果您保持这种方式,您将需要更改其他矩阵数学例程以使其工作相同。

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

typedef struct 
    int *elements;
    int rows;
    int columns;
 matrix;

void read_matrix(matrix *z) 

    int d1, d2, val;

    printf("\nWhat is the first dimension of the array? ");
    int result = scanf("%d", &d1);

    if (result != 1) 
        fprintf(stderr, "Something went wrong with your first dimension!\n");
        exit(1);
    

    printf("What is the second dimension of the array? ");
    result = scanf("%d", &d2);
    if (result != 1) 
        fprintf(stderr, "Something went wrong with your second dimension!\n");
        exit(1);
    

    printf("Matrix Dimension is %dx%d\n", d1, d2);

    z->elements = calloc(d1 * d2, sizeof(int));
    z->rows = d1;
    z->columns = d2;

    int x = 0;
    int j = 0;

    printf("\n");

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

        x++;

        for (int y = 0; y < d2; y++) 
            printf("Enter the value for row %d column %d: ", x, y + 1);
            result = scanf("%d", &val);
            if (result != 1) 
                fprintf(stderr, "Something went wrong while reading value (%d, %d)\n", x, y + 1);
                exit(1);
            

            z->elements[j++] = val;
        
    


void deallocate(matrix *c) 

    free(c->elements);

    c->elements = NULL;
    c->rows = 0;
    c->columns = 0;


void print(matrix *z) 

    int x = 0;

    for (int i = 0; i < z->rows; i++) 

        printf("[  ");

        for (int j = 0; j < z->columns; j++) 

            printf("%-4d", z->elements[x++]);
        

        printf("]\n");
    


void multiply(matrix *a, matrix *b, matrix *c) 

    if (a->columns !=  b->rows) 
        fprintf(stderr, "The inner dimensions of your matrices do not match! Multiplication cannot be done!\n");
        exit(1);
    

    c->elements = calloc(a->rows * b->columns, sizeof(int));
    c->columns = b->columns;
    c->rows = a->rows;

    int alc = 0;

    for (int x = 0; x < a->rows; x++) 

        for (int y = 0; y < b->columns; y++) 

            int value = 0;

            for (int z = 0; z < b->rows; z++) 

                value += a->elements[z + x * a->columns] * b->elements[y + z * b->columns];
            

            c->elements[alc++] = value;
        
    


int main() 

    matrix a, b, c;

    read_matrix(&a);
    read_matrix(&b);

    multiply(&a, &b, &c);

    printf("The answer of Matrix (a * b) is \n\n");
    print(&a);
    printf("\n  *\n\n");
    print(&b);
    printf("\n  =\n\n");
    print(&c);
    printf("\n");

    deallocate(&a);
    deallocate(&b);
    deallocate(&c);

    return 0;

【讨论】:

对像这样的半透明(仅由函数调用访问)结构的另一个合理解决方案是将typedef 结构作为结构的大小为 1 的数组的名称。 GMP 使用mpz_t 完成此操作,因此您可以使用(大部分)无缝隐式逐指针传递语义来传递它们,避免显式接受指针和传递指针的需要,同时仍然使基本结构的堆栈分配变得简单。 感谢您的回答!所有的功能和他们的合作伙伴都按照我的教授对实验室的要求。如果我可以改变,那么我也会改变。谢谢你的回答! @T.Gon 有不同的机制来表达对帖子的感谢。如果您认为帖子(问题也需要投票)有用(有帮助?启发性?),upvote it(10 次代表)。如果某个答案解决了您的问题(或对找到解决方案最有帮助),接受它(15 次代表)。如果您认为某个问题的最佳答案值得加分,请发起赏金活动(将声誉从您的帐户转移,也可能转移到其他人的帐户)。

以上是关于矩阵乘法 - C的主要内容,如果未能解决你的问题,请参考以下文章

矩阵的乘法运算法则

03-乘法和逆矩阵

c语言的矩阵乘法问题 初学者求助

矩阵乘法 - C

矩阵乘法

算法导论—矩阵链乘法(动态规划)