-1

How to normalize a matrix?

Suppose I have a 2x3 matrix:
1 2 3
4 5 6 The normalized matrix would be:
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))

This is my sample code:

#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;  
    }  
  • I don't know what's wrong with my code it gives me the square to be 0.000 0.000 and norm is all 0.000 – Genevieve Baguhin Engalan Feb 14 '16 at 14:13
  • You understand that many of your declarations are `int` instead of `double` or `float`, right? So for instance your `printf` that used `%lf` format is guaranteed to fail if you pass it `square[r]`, since that will be passed as an `int`. Fix your declarations to be `double`. – Tom Karzes Feb 14 '16 at 14:32
  • And worse, your `norm` matrix is `int`. That means any fractional part will be discarded. Get rid of *all* the `int` declarations for your matrix values. – Tom Karzes Feb 14 '16 at 14:34
  • 1
    Also, *turn on compiler warnings* and *fix them* before posting code here. Modern C compilers should warn about the incorrect data types being passed to `printf`. – Tom Karzes Feb 14 '16 at 14:41

2 Answers2

4

Why are you using == here:

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);  
       }  

It should be:

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

The same here:

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

It should be:

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

And you should be careful here:

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

Are you sure about use int for all of this declarations? I think you should use double or float instead, at least in some of them.

2

There are some problems in your code, I'll try to address the most important ones.

Your norm matrix is a 2D array of int as inputMatrix, but you have to use an array of float or double to correctly store the result and to perform the right calculation. In C if both of the terms of a division are integers types an integer division (like: 3/2 = 1, not 1.5) is performed, which is not what you need.

Another mistake is to use == instead of = to perform an assignment. In C == is the 'equal to' relational operation.

EDIT

As @chux pointed out it would be wiser to choose a more accurate type for a and square[]. Using long long int will (may) prevent numeric overflow in case the elements of the matrix are too big for their square or the sum of them to be reprensented by an int.

Be aware that if you decide to use double instead there are other subtle numerical issues concernig the sum of small number (and the order in which it is performed) represented by floating point types. So, as a partial remedy, you can use long double (if it really has more precision then double in your environment) for a and square.

EDIT 2

In the question and in comment you say that the first element of each row of the matrix is supposed to be "constant in the matrix" so it doesn't take part to the sum of squares in your code and in the example you gave, but in both of them they are updated in the next loop. I'm not sure of what is going on, so I corrected my code to mimic the behavior of yours.

Here is a working corrected version of your code:

#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;  
}

I keep the input matrix of integer type, but it would be better to use double for that too. As i added a print loop for the original matrix, the final output is:

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
Bob__
  • 12,361
  • 3
  • 28
  • 42
  • Unclear why continuing with `float` in `float a; a = inputMatrix[r][c];`. Perhaps `long long` for `a` and `square[]`? – chux - Reinstate Monica Feb 14 '16 at 17:53
  • @chux ops, you are right I've missed that. I edited the answer and used int as the OP initialize its matrix so, but, as said, I think it would be better using double from the biginning. – Bob__ Feb 14 '16 at 18:07
  • 1
    @chux I wanted to keep it simple, but on second thought, I agree with you that it's better address that possible issue – Bob__ Feb 14 '16 at 19:26
  • I looked into how to define a integer that was twice as wide with [this](http://stackoverflow.com/q/25982992/2410359) . But I agree with you, this is more like a FP problem fro `double`, etc. – chux - Reinstate Monica Feb 14 '16 at 20:31
  • @Bob chux Thank you so much. I did not include the first row for it is my constant in the matrix. but it's ok.. thank you for the big help. – Genevieve Baguhin Engalan Feb 15 '16 at 01:42
  • @GenevieveBaguhinEngalan you're welkome and thanks for comment, I'll correct my answer accordingly. Can you please elaborate a little on the constness of the first element? It's where you store the known vector of a linear system of equations? – Bob__ Feb 15 '16 at 09:04
  • @Bob__ this is a linear programming problem where my constraints are Ax_i<=b. for example I have a set of constraints, 2x_1 + x_2 <=1500 x_1 + x_2 <= 1200 then I will write this in matrix as: 1500 2 1 1200 1 1 That's why I did not include the first element. – Genevieve Baguhin Engalan Feb 17 '16 at 01:41
  • @Bob__ this is a linear programming problem where my constraints are Ax_i<=b. for example I have a set of constraints, 2x_1 + x_2 <=1500 x_1 + x_2 <= 1200 then I will write this in matrix as: 1500 2 1 1200 1 1 That's why I did not include the first element. – Genevieve Baguhin Engalan Feb 17 '16 at 01:50