user10429345
user10429345

Reputation:

raise a Matrix to the power in c

Trying to raise a matrix to the power of p, but I dont find the mistake. Can anyone help and explain the problem? I just got started in programming in C so thank you very much for your help. The user should enter a matrix and it should be raised to the power of p.

int main() {
    int n, p;
    printf("Number of Rows/Colums of square matrix: ");
    scanf("%d", &n);
    printf("to the power of: ");
    scanf("%d", &p);
    int m[n][n];
    int r[n][n];

    printf("Elements\n");
    for (int b = 0; b < n; b++) {
        for (int d = 0; d < n; d++) {
            printf("[%d][%d] = ", b + 1, d + 1);
            scanf("%d", &m[b][d]);
        }
    }

    int sum = 0;
    for (int i = 0; i < p; i++) {
        for (int b = 0; b < n; b++) {
            for (int d = 0; d < n; d++) {
                for (int k = 0; k < n; k++) {
                    sum += m[b][k] * m[k][d];
                }
                r[b][d] = sum;
                sum = 1;
            }
        }

        for (int b = 0; b < n; b++) {
            for (int d = 0; d < n; d++) {
                m[b][d] = r[b][d];
                r[b][d] = 0;
            }
        }
    }

    printf("RESULT:-\n");

    for (int c = 0; c < n; c++) {
        for (int d = 0; d < n; d++) {
            printf("%d   ", m[c][d]);
        }
        printf("\n");
    }

    getch();
    return 0;
}

Upvotes: 2

Views: 8820

Answers (4)

chqrlie
chqrlie

Reputation: 144715

There are multiple issues in your code:

  • you should use a temporary matrix t to compute the result of r * m and copy that to r before the next step.
  • sum should be re-initialized to 0, or better, initialized to 0 before the k loop.

Here is a corrected version:

#include <stdio.h>

int main() {
    int n, p;
    printf("Number of Rows/Colums of square matrix: ");
    if (scanf("%d", &n) != 1 || n <= 0)
        return 1;
    printf("to the power of: ");
    if (scanf("%d", &p) != 1 || p < 0)
        return 1;

    int m[n][n];
    int r[n][n];
    int t[n][n];

    printf("Elements\n");
    for (int b = 0; b < n; b++) {
        for (int d = 0; d < n; d++) {
            printf("[%d][%d] = ", b + 1, d + 1);
            if (scanf("%d", &m[b][d]) != 1)
                return 1;
            r[b][d] = b == d; // initialize r to identity matrix
        }
    }
    for (int i = 0; i < p; i++) {
        for (int b = 0; b < n; b++) {
            for (int d = 0; d < n; d++) {
                int sum = 0;
                for (int k = 0; k < n; k++) {
                    sum += r[b][k] * m[k][d];
                }
                t[b][d] = sum;
            }
        }
        for (int b = 0; b < n; b++) {
            for (int d = 0; d < n; d++) {
                r[b][d] = t[b][d];
            }
        }
    }

    printf("RESULT:\n");
    for (int c = 0; c < n; c++) {
        for (int d = 0; d < n; d++) {
            printf("%3d ", r[c][d]);
        }
        printf("\n");
    }
    return 0;
}

Notes:

  • The above code works for positive powers, including 0 which produces the identity matrix.

  • Note however that this method is inefficient for large powers and int is likely to overflow for large powers anyway.

Upvotes: 1

duffymo
duffymo

Reputation: 308763

I'd recommend that you decompose this complex problem into smaller problems.

Create smaller functions, test them to make sure they're working, and then take the next step calling those until you have the full set.

You need to start with a matrix: a[m][n]. Should the values it holds be integers, floats, doubles? Make sure you can create a matrix of different sizes. What should your restrictions on rows and columns be?

Begin with methods to read and write your matrix.

Next is a method to multiple two matricies together: c[m][n] = a[m][k]*b[k][n]. The number of columns in a has match the number of rows in b or you can't multiply.

Raising a matrix to an integer power p > 1 means multiplying the starting matrix by itself p times. Can you see that one requirement is that the starting matrix has to be square? (# rows == # columns) If that's not true, you can't raise to an integer power.

You'll need a loop to raise to a power p times. You will call your matrix multiplication method c = mult(a, b) each time through the loop. Each pass through will take the output from the previous call and make it the first matrix in the call: c = mult(c, b).

If you attack the problem this way you should be able to solve it. Be sure to test each step carefully before you move on.

This is called decomposition. It's bedrock for problem solving in general and computer science in particular.

Upvotes: 2

Jabberwocky
Jabberwocky

Reputation: 50775

Your program logic is wrong at several levels.

This is your corrected program. There is still room for improvement (breaking the code down into functions, using better variable naming, using a more efficient algorithm than brute matrix multiplication, treating correctly the case where p is 0), but I tried to stick as much as possible to the original wrong implementation.

This is the approach: we have three matrixes: r the result, m the matrix provided by user, and temp a temporary matrix.

  1. Initially we copy m into r, this is the result for p = 1
  2. We repeat steps 3 and 4 p - 1 times
  3. We multiply r and m and put the result into temp
  4. We copy temp into r
  5. Now r contains the m elevated to the power of p.

#include <stdio.h>

int main() {
  int n, p;
  printf("Numer of Rows/Colums of sq matrix: ");
  scanf("%d", &n);
  printf("to the power of: ");
  scanf("%d", &p);
  int m[n][n];
  int r[n][n];
  int temp[n][n];

  printf("Elements\n");
  for (int b = 0; b < n; b++) {
    for (int d = 0; d < n; d++) {
      printf("[%d][%d] = ", b + 1, d + 1);
      scanf("%d", &m[b][d]);
    }
  }

  // r = m
  // temp = m
  for (int b = 0; b < n; b++) {
    for (int d = 0; d < n; d++) {
      r[b][d]   = m[b][d];
    }
  }

  for (int i = 0; i < p - 1; i++)  // p - 1 because for p = 1, r already 
  {                                // contains the result
    int sum = 0;

    // temp = r * m
    for (int b = 0; b < n; b++)
    {
      for (int d = 0; d < n; d++)
      {
        for (int k = 0; k < n; k++)
        {
          sum += m[b][k] * r[k][d];
        }
        temp[b][d] = sum;
        sum = 0;
      }
    }

    // r = temp
    for (int b = 0; b < n; b++) {
      for (int d = 0; d < n; d++) {
        r[b][d] = temp[b][d];
      }
    }
  }

  printf("RESULT:\n");

  for (int c = 0; c < n; c++)
  {
    for (int d = 0; d < n; d++)
    {
      printf("%d   ", r[c][d]);
    }
    printf("\n");
  }

  return 0;
}

Upvotes: 2

Alexander James Pane
Alexander James Pane

Reputation: 648

I think you have various logical problems in your code.

The outer loop is wrong since you loop one time less the power quantity.

Secondly you need a buffer matrix the way you wrote your code.

Another problem is that when you multiply the row/column values, you always use the original matrix. This is logically wrong, you need to multiply the matrix computed up the current power by the original matrix.

I also don't understand why you reset the sum variable to 1 and not 0.

Something like this should work:

#include <stdio.h>

int main() {
int n, p;
printf("Numer of Rows/Colums of sq matrix: ");
scanf("%d", &n);
printf("to the power of: ");
scanf("%d", &p);
int m[n][n];
int r[n][n];
int tmp[n][n];

printf("Elements\n");
for ( int b = 0 ; b < n ; b++ ) {
    for ( int d = 0 ; d < n ; d++ ) {
        printf("[%d][%d] = ", b+1, d+1);
        scanf("%d", &m[b][d]);
        r[b][d] = m[b][d];
    }
}

int sum = 0;
//you loop 1 time less of the power
for (int i = 0; i < p - 1; i++)
{
    for ( int b = 0 ; b < n ; b++ )
    {
        for (int d = 0 ; d < n ; d++ )
        {
            for (int k = 0 ; k < n ; k++ )
            {
                sum += r[b][k]*m[k][d];
            }
            tmp[b][d] = sum;
            sum = 0;
        }
    }

    for ( int b = 0 ; b < n ; b++ ) {
        for ( int d = 0 ; d < n ; d++ ) {
            //m[b][d] = r[b][d];
            r[b][d] = tmp[b][d];
        }
    }
}

printf("RESULT:-\n");

for (int c = 0 ; c < n ; c++ )
{
    for (int d = 0 ; d < n ; d++ )
    {
        printf("%d   ", r[c][d]);
    }
    printf("\n");
}

getchar();
return 0;
}

I would just point out that this solution probably does not work with p < 1

Upvotes: 2

Related Questions