【问题标题】:How to normalize a matrix in C?如何标准化C中的矩阵?
【发布时间】:2026-01-08 14:10:01
【问题描述】:

如何对矩阵进行归一化?

假设我有一个 2x3 矩阵:
1 2 3
4 5 6 归一化矩阵为:
1/sqrt(pow(2,2) + pow(3,2)) 2/sqrt(pow(2,2) + pow(3,2)) 3/sqrt(pow(2,2) + pow(3,2))
4/sqrt(pow(5,2) + pow(6,2)) 5/sqrt(pow(5,2) + pow(6,2)) 6/sqrt(pow(5,2) + pow(6,2))

这是我的示例代码:

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

int main(){  
    int rows, cols, rowCounter, colCounter, r, c;  
    int initial[100], inputMatrix[100][100], rowSum[100] = {0}, norm[100][100], square[100] = {0};


    printf("Enter size of a matrix\n");
    scanf("%d %d", &rows, &cols);
    printf("Enter matrix of size %dX%d\n", rows, cols);
    /* Input matrix */
    for(rowCounter = 0; rowCounter < rows; rowCounter++){
        for(colCounter = 0; colCounter < cols; colCounter++){
            scanf("%d", &inputMatrix[rowCounter][colCounter]);
        }
    }



    for(r = 0; r < rows; r++)  
       {  
           for(c = 1; c < cols; c++)  
           {  
               float a;  
               a == inputMatrix[r][c];  
                square[r] += pow(a, 2);  
           }  
           printf("%.2lf ", square[r]);  
       }  

        for(rowCounter = 0; rowCounter < rows; rowCounter++)  
       {  
           for(colCounter = 0; colCounter < cols; colCounter++)  
           {  
               norm[rowCounter][colCounter] == (inputMatrix[rowCounter][colCounter]) / sqrt(square[rowCounter]);  
           }  
       }  
       printf("\nNormalized Matrix:\n");  
       for(rowCounter = 0; rowCounter < rows; rowCounter++)  
       {  
           for(colCounter = 0; colCounter < cols; colCounter++)  
           {  
               printf("%.3lf ", norm[rowCounter][colCounter]);  
           }  
           printf("\n");  
       }  

        getch();  
        return 0;  
    }  

【问题讨论】:

  • 我不知道我的代码出了什么问题,它给我的平方是 0.000 0.000,标准都是 0.000
  • 您知道您的许多声明是int 而不是doublefloat,对吗?因此,例如,如果您通过square[r],使用%lf 格式的printf 肯定会失败,因为它将作为int 传递。将您的声明修正为double
  • 更糟糕的是,您的norm 矩阵是int。这意味着任何小数部分都将被丢弃。摆脱矩阵值的所有 int 声明。
  • 另外,在此处发布代码之前,打开编译器警告修复它们。现代 C 编译器应该警告传递给 printf 的数据类型不正确。

标签: c matrix


【解决方案1】:

你为什么在这里使用==

for(r = 0; r < rows; r++)  
   {  
       for(c = 1; c < cols; c++)  
       {  
           float a;  
           a == inputMatrix[r][c];   //look here
            square[r] += pow(a, 2);  
       }  

应该是:

for(r = 0; r < rows; r++)  
   {  
       for(c = 1; c < cols; c++)  
       {  
           float a;  
           a = inputMatrix[r][c];  
            square[r] += pow(a, 2);  
       }  

这里也一样:

norm[rowCounter][colCounter] == (inputMatrix[rowCounter][colCounter]) / sqrt(square[rowCounter]);

应该是:

norm[rowCounter][colCounter] = (inputMatrix[rowCounter][colCounter]) / sqrt(square[rowCounter]);

你应该在这里小心:

int initial[100], inputMatrix[100][100], rowSum[100] = {0}, norm[100][100], square[100] = {0};

您确定所有这些声明都使用int 吗? 我认为您应该改用doublefloat,至少在其中一些中。

【讨论】:

【解决方案2】:

您的代码中存在一些问题,我将尝试解决最重要的问题。

您的norm 矩阵是一个二维数组 int 为inputMatrix,但您必须使用浮点数或双精度数组才能正确存储结果并执行正确的计算。在 C 中,如果除法的两个项都是整数类型,则执行整数除法(例如:3/2 = 1,而不是 1.5),这不是您需要的。

另一个错误是使用== 而不是= 来执行分配。在 C 中,== 是“等于”关系运算。

编辑

正如@chux 指出的那样,为asquare[] 选择更准确的类型会更明智。使用long long int 将(可能)防止数字溢出,以防矩阵的元素太大而无法使用它们的平方或它们的总和以int 表示。

请注意,如果您决定使用 double 来代替,还有其他一些细微的数字问题,例如浮点类型表示的小数的总和(以及执行它的顺序)。因此,作为部分补救措施,您可以使用long double(如果它在您的环境中确实比double 更精确)用于asquare

编辑 2

在问题和评论中,您说矩阵每一行的第一个元素应该是“矩阵中的常数”,因此它不参与代码和示例中的平方和你给了,但在他们两个中,它们都在下一个循环中更新。我不确定发生了什么,所以我更正了我的代码以模仿你的行为。

这是您的代码的工作更正版本:

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

int main() {  
    int rows, cols, r, c;  
    // you may think about dynamical allocation here
    int inputMatrix[100][100], rowSum[100] = {0};
    // it's better to use a type that can manage bigger numbers to avoid numeric overflow
    long long int a, square[100] = {0}; 
    // your starting matrix can be a matrix of int but the normalized one need to
    // contain floating point numbers
    double norm[100][100], k;

    printf("Enter size of a matrix\n");
    scanf("%d %d", &rows, &cols);
    printf("Enter matrix of size %dX%d\n", rows, cols);
    /* Input matrix */
    for ( r = 0; r < rows; r++) {
        for (c = 0; c < cols; c++) {
            scanf("%d", &inputMatrix[r][c]);
            //     ^^ if you are scanning integer numbers... 
        }
    }

    printf("\nrows: %d cols: %d elements:\n",rows,cols);  
    for( r = 0; r < rows; r++) {  
        for( c = 0; c < cols; c++) {  
            printf("%d ", inputMatrix[r][c]);
            // ...  ^^ you should print integer numbers
        }  
        printf("\n");  
    }  

    for (r = 0; r < rows; r++)  {  
        for (c = 1; c < cols; c++) {
        //      ^^^ I don't know why you skip this here
            a = inputMatrix[r][c];
            //^ You have to assign, not to compare!
            square[r] += a * a;
            //           ^^^^^ no need to call pow()
        }  
        printf("Sum of squares of row %d: %lld\n",r,square[r]);
        //             square contains int ^^
        // It would be nice and safer if you check here if square == 0 to avoid a
        // division by zero and probably detect bad input data
    }  

    for ( r = 0; r < rows; r++ ) {
        // It's far more efficient to precalculate this term, even if compilers
        // could be smart enough to do it for you. You may want to store those
        // values in an array of doubles instead of the (sum of) squares
        k = 1.0 / sqrt(square[r]);
        for( c = 0; c < cols; c++ ) {  
            norm[r][c] = k * inputMatrix[r][c] ;
            // again,  ^ assign not compare
        }  
    }

    // you can add the printf to the previous loop...
    printf("\nNormalized Matrix:\n");  
    for( r = 0; r < rows; r++) {  
        for( c = 0; c < cols; c++) {  
            printf("%.3lf ", norm[r][c]);
            //      ^^^^^ norm contains double 
        }  
        printf("\n");  
    }  

    return 0;  
}

我保留整数类型的输入矩阵,但最好也使用双精度。当我为原始矩阵添加一个打印循环时,最终输出是:

rows: 2 cols: 3 elements:
1 2 3 
4 5 6 
Sum of squares of row 0: 13
Sum of squares of row 1: 61

Normalized Matrix:
0.277 0.555 0.832 
0.512 0.640 0.768

【讨论】:

  • 不清楚为什么在float a; a = inputMatrix[r][c]; 中继续使用float。也许long long 代表asquare[]
  • @chux ops,你说得对,我错过了。我编辑了答案并使用 int 作为 OP 初始化它的矩阵,但是,如前所述,我认为使用 biginning 中的 double 会更好。
  • @chux 我想保持简单,但转念一想,我同意你的观点,最好解决这个可能的问题
  • 我研究了如何使用 this 定义两倍宽的整数。但我同意你的看法,这更像是来自double 等的 FP 问题。
  • @Bob chux 非常感谢。我没有包括第一行,因为它是我在矩阵中的常数。但没关系..感谢您的大力帮助。