Что не так с функцией multiplyTwoMatrices () в этом C-коде для поиска Фибоначчи с использованием умножения матриц? - PullRequest
0 голосов
/ 31 мая 2018
#include<stdio.h>

void multiplyTwoMatrices(int (*)[2], int[][2], int[][2]);
void copyMatrix(int[][2], int[][2]);
void powerAMatrix(int[][2], int[][2], int);

int main()
{
    int num;
    scanf("%d", &num);

    int i;
    for(i = -1; i <= num; i++)
    {
        printf("\n%d", fib(i));
    }
}

int fib(int num)
{
    if(num <= 0)
    {
        return 0;
    }
    else
    {
        int matrix[2][2] = {{1, 1}, {1, 0}};
        //int fibMatrix[2][2] = powerAMatrix(matrix[2][2], num);
        int fibMatrix[2][2];
        powerAMatrix(fibMatrix, matrix, num);
        return getFibNum(fibMatrix);
    }
}

void powerAMatrix(int fibMatrix[2][2], int matrix[2][2], int num)
{
    //fibMatrix = matrix;
    copyMatrix(fibMatrix, matrix);
    int i = 0;
    for(i = 1; i < num; i++)
    {
        //fibMatrix = fibMatrix * matrix;
        multiplyTwoMatrices(fibMatrix, fibMatrix, matrix);
    }
}

void copyMatrix(int destinationMatrix[2][2], int sourceMatrix[2][2])
{
    int i = 0; int j = 0;
    for(i = 0; i < 2; i++)
        for(j = 0; j < 2; j++)
            destinationMatrix[i][j] = sourceMatrix[i][j];
}

void multiplyTwoMatrices(int multipliedMatrix[2][2], int matrixA[2][2], int matrixB[2][2])
{

    int i = 0; int j = 0; int k = 0;
    for(i = 0; i < 2; i++)
    {
        for(j = 0; j < 2; j++)
        {
            multipliedMatrix[i][j] = 0;     //or just initialize it as a zero matrix.
            for(k = 0; k < 2; k++)
            {
                multipliedMatrix[i][j] += (matrixA[i][k] * matrixB[k][j]);
            }
        }
    }
                    //working alternative
    /*
    int x =  matrixA[0][0]*matrixB[0][0] + matrixA[0][1]*matrixB[1][0];
    int y =  matrixA[0][0]*matrixB[0][1] + matrixA[0][1]*matrixB[1][1];
    int z =  matrixA[1][0]*matrixB[0][0] + matrixA[1][1]*matrixB[1][0];
    int w =  matrixA[1][0]*matrixB[0][1] + matrixA[1][1]*matrixB[1][1];

    multipliedMatrix[0][0] = x;
    multipliedMatrix[0][1] = y;
    multipliedMatrix[1][0] = z;
    multipliedMatrix[1][1] = w;
    */
}

int getFibNum(int fibMatrix[2][2])
{
    return fibMatrix[0][1];
}

Функция multiplyTwoMatrices (), кажется, работает, только если вместо того, который используется в настоящее время, используется «рабочая альтернатива» (код, закрытый в комментариях внутри этой функции).Я не могу понять, что происходит с этим кодом.Приветствуется небольшая помощь.

Ожидаемый результат: 0 0 1 1 2 3 5 8 ...

Выход: 0 0 1 1 1 1 1 1 ...

1 Ответ

0 голосов
/ 01 июня 2018

, пока ваша функция умножения верна, она не будет работать правильно, если в качестве целевого используется один из операндов;если это так, то операнд изменяется там во время вычисления.

Либо требуется, чтобы multipliedMatrix отличался от matrixA и matrixB (что было бы предпочтительным), либо имел временныйМатрица там и скопировать его в результат!


PS было бы намного проще обернуть класс матрицы в структуру:

struct intmatrix2x2 {
    int values[2][2];
};

это сделало бы неявные копии при вызове функций;и вместо copyMatrix вы можете сказать:

struct intmatrix2x2 b = a;

, и ваше умножение может читаться как

struct intmatrix2x2 multiply(struct intmatrix2x2 a, struct intmatrix2x2 b)
{
    struct intmatrix2x2 result;
    int i = 0; int j = 0; int k = 0;
    for(i = 0; i < 2; i++)
    {
        for(j = 0; j < 2; j++)
        {
            result.values[i][j] = 0;     //or just initialize it as a zero matrix.
            for(k = 0; k < 2; k++)
            {
                result.values[i][j] += a.values[i][k] * b.values[k][j]);
            }
        }
    }
    return result;
}

, и вы можете использовать его как

struct intmatrix2x2 result = multiply(a, b);
...