c - 如何通过在C中用零填充来使矩阵平方

标签 c matrix

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

这是我糟糕的尝试(我对 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

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

谢谢你的帮助

最佳答案

将添加的内存归零(新行)

如果我明白你在做什么,你最初可以通过使用 calloc 而不是 A 中的所有值初始化为 0 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;
}

一个简短的例子,把它放在一起,并允许你通过传递 -DWMEMSET 作为定义在 memset() 之间进行选择,或者默认使用 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

仅对最后一列进行归零

如果您需要将添加的列而不是行归零,那么您将需要手动将原始行复制到新分配的 block 的行中,然后释放原始行。为此,您必须更改 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;
}

本质上,您正在编写自定义 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);
}

检查一下,如果您还有其他问题,请告诉我。

关于c - 如何通过在C中用零填充来使矩阵平方,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64437416/

相关文章:

c - GLKit 的 GLKMatrix "Column Major"怎么样?

c - 将字符串写入十六进制转换器

c++ - 双指针和指针数组的区别

c - 一个数组的最后一个元素被下一个数组的第一个元素覆盖

c - 销毁 C 中的双向链表

java - 表示带有列/行标签的矩阵

C++ 如何将整数和长整型转换为 char 数组

R:两个数值矩阵的快速笛卡尔积计算

javascript - 如何在 webgl 中围绕 mousedrag 中的场景旋转(模拟相机在某个位置周围移动)

java - 对二维 double 组进行排序