首页 > 解决方案 > 如何通过在C中用零填充矩阵来使其平方

问题描述

我目前正在尝试通过填充零列来完成 am by n 矩阵(其中 m 大于或等于 n)。主要问题是我的矩阵存储在 double* 而不是 double** 中。因此,我的矩阵不是看起来像 2d 矩阵,它实际上是一个向量,它将矩阵的行粘在一行中。

这是我糟糕的尝试(我对 C 编程语言很陌生......)

void square_my_matrix(double* A, int n){//m is a global variable
    for(int i = 0; i < m; i++){
        for(int j = 0; j < m; j++){
            if(i*m+j > j*m+n) continue;
            else A[i*m+j] = 0.0;
}

int main(){
    double* A;
    A = malloc(m*n*sizeof(*A));
    buildMatrix(); //this fills my matrix with some data
    printMatrix(m,n,A); //this prints my matrix in a 2d fashion to make it clearer

    if(m>n){
        A = realloc(A, m*m*sizeof(*A));
        square_my_matrix(A, n);
    }
    printMatrix(m,m,A);
}

我的第一个printMatrix

1.00 1.00
1.00 3.00
1.00 5.00
1.00 7.00

打电话后square_my_matrix我期待(printMatrix再次打电话时)

1.00 1.00 0.00 0.00
1.00 3.00 0.00 0.00
1.00 5.00 0.00 0.00
1.00 7.00 0.00 0.00

但我得到了这个

1.00 1.00 1.00 3.00
0.00 5.00 1.00 7.00
0.00 0.00 0.00 0.00
0.00 0.00 0.00 0.00

我可能搞砸了一些明显的东西,但我不知道是什么。

谢谢您的帮助

标签: cmatrix

解决方案


归零添加的内存(新行)

如果我了解您在做什么,您最初可以使用而不是初始化所有值A0calloc会将malloc所有字节设置为零)。然后跟随您realloc,您可以使用memset()将您分配的新内存归零。(如果您需要将添加的列归零,请参阅此答案的第二部分)

您可以将分配的新内存归零realloc(),例如

double*A;
A = calloc (m * n, sizeof *A);
if (A == NULL) {          /* validate EVERY allocation */
    perror ("calloc-A");
    exit (EXIT_FAILURE);
}

buildMatrix(); //this fills my matrix with some data
printMatrix(m,n,A); //this prints my matrix in a 2d fashion to make it clearer

if (m > n) {
    void *tmp = realloc (A, m * m * sizeof *A);  /* ALWAYS realloc with a temporary pointer */
    if (!tmp) {           /* validate EVERY allocation */
        perror ("realloc-A");
        exit (EXIT_FAILURE);
    }
    A = tmp;              /* assign reallocated block */
    /* set new memory zero */
    memset (A + m * n, 0, m * (m - n) * sizeof *A);
    
    // square_my_matrix(A, n);
}
printMatrix(m,m,A);

如果您确实想使用square_my_matrix(),那么您将删除memset()上面并使用:

void square_my_matrix (double* A, int n)
{
    for (int i = n; i < m; i++)
        for (int j = 0; j < m; j++)
                A[i * m + j] = 0.0;
}

一个简短的例子把它放在一起,允许你memset()通过-DWMEMSET作为定义传递,或者默认使用square_my_matrix(),你可以这样做:

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

#define m      10
#define nbegin  8

void square_my_matrix (double* A, int n)
{
    for (int i = n; i < m; i++)
        for (int j = 0; j < m; j++)
                A[i * m + j] = 0.0;
}

void printMatrix (int rows, int cols, double *A)
{
    /* check overflow in multiplication of rows * cols here */
    
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++)
            printf (" %3g", A[i * cols + j]);
                putchar ('\n');
    }
}

int main (void) {
    
    int n = nbegin,
        v = 1;
    double *A;
    
    A = calloc (m * n, sizeof *A);
    if (A == NULL) {          /* validate EVERY allocation */
        perror ("calloc-A");
        exit (EXIT_FAILURE);
    }
    
    // buildMatrix(); //this fills my matrix with some data
    for (int i = 0; i < m; i++)
        for (int j = 0; j < n; j++)
            A[i * n + j] = v++;
    
    
    printMatrix (m,n,A); //this prints my matrix in a 2d fashion to make it clearer
    
    if (m > n) {
        /* ALWAYS realloc with a temporary pointer */
        void *tmp = realloc (A, m * m * sizeof *A);
        if (!tmp) {           /* validate EVERY allocation */
            perror ("realloc-A");
            exit (EXIT_FAILURE);
        }
        A = tmp;              /* assign reallocated block */
#ifdef WMEMSET
        /* set new memory zero */
        memset (A + m * n, 0, m * (m - n) * sizeof *A);
#else
        square_my_matrix(A, n);
#endif
    }
    printMatrix (m,m,A);
    
}

示例使用/输出

无论是否WMEMSET定义,输出都是相同的:

$ ./bin/mxn2mm
   1   2   3   4   5   6   7   8
   9  10  11  12  13  14  15  16
  17  18  19  20  21  22  23  24
  25  26  27  28  29  30  31  32
  33  34  35  36  37  38  39  40
  41  42  43  44  45  46  47  48
  49  50  51  52  53  54  55  56
  57  58  59  60  61  62  63  64
  65  66  67  68  69  70  71  72
  73  74  75  76  77  78  79  80
   1   2   3   4   5   6   7   8   9  10
  11  12  13  14  15  16  17  18  19  20
  21  22  23  24  25  26  27  28  29  30
  31  32  33  34  35  36  37  38  39  40
  41  42  43  44  45  46  47  48  49  50
  51  52  53  54  55  56  57  58  59  60
  61  62  63  64  65  66  67  68  69  70
  71  72  73  74  75  76  77  78  79  80
   0   0   0   0   0   0   0   0   0   0
   0   0   0   0   0   0   0   0   0   0

仅清零最后一列

如果您需要将添加的列而不是行归零,则需要手动将原始行复制到新分配块的行,然后释放原始行。为此,您必须更改square_my_matrix()为获取指针的地址(指针到指针)而不是简单的指针,这将允许您更新A函数中的位置。例如:

void square_my_matrix (double **A, int n)
{
    double *b = calloc (m * m, sizeof *b);
    if (!b) {
        perror ("calloc-b");
        exit (EXIT_FAILURE);
    }
    
    for (int i = 0; i < m; i++)
        memcpy (b + i * m, *A + i * n, n * sizeof **A);
    
    free (*A);
    *A = b;
}

本质上,您正在编写 custom realloc()

然后你会调用这个函数:

    square_my_matrix (&A, n);

示例输出

那么你的输出将是:

$ ./bin/mxn2mm
   1   2   3   4   5   6   7   8
   9  10  11  12  13  14  15  16
  17  18  19  20  21  22  23  24
  25  26  27  28  29  30  31  32
  33  34  35  36  37  38  39  40
  41  42  43  44  45  46  47  48
  49  50  51  52  53  54  55  56
  57  58  59  60  61  62  63  64
  65  66  67  68  69  70  71  72
  73  74  75  76  77  78  79  80
   1   2   3   4   5   6   7   8   0   0
   9  10  11  12  13  14  15  16   0   0
  17  18  19  20  21  22  23  24   0   0
  25  26  27  28  29  30  31  32   0   0
  33  34  35  36  37  38  39  40   0   0
  41  42  43  44  45  46  47  48   0   0
  49  50  51  52  53  54  55  56   0   0
  57  58  59  60  61  62  63  64   0   0
  65  66  67  68  69  70  71  72   0   0
  73  74  75  76  77  78  79  80   0   0

为了完成,main()上面示例中的更新将减少为:

int main (void) {
    
    int n = nbegin,
        v = 1;
    double *A;
    
    A = calloc (m * n, sizeof *A);
    if (A == NULL) {          /* validate EVERY allocation */
        perror ("calloc-A");
        exit (EXIT_FAILURE);
    }
    
    // buildMatrix(); //this fills my matrix with some data
    for (int i = 0; i < m; i++)
        for (int j = 0; j < n; j++)
            A[i * n + j] = v++;
    
    printMatrix (m,n,A);
    if (m > n)
        square_my_matrix (&A, n);
    printMatrix (m,m,A);
}

如果您还有其他问题,请仔细查看并告诉我。


推荐阅读