singlepost

Возведение матрицы в степень на С++ << На главную или назад  

Даны натуральное число p и вещественные квадратные матрицы A,B,C размером 4х4 . Получить (A*B*C)^p , используя функцию Mult(A,B) возвращающую результат умножения двух матриц.

Язык – Борланд С++

Я вроде со всем разобралась кроме возведения в степень , помогите доделать программу)

Вот мой текст:

#include <iostream.h>
#include <math.h>
#include <stdlib.h>
#include <conio.h>
void mult(double *a,double *b,double *q)
{
int i,j,k;
for(i=0;i<4;i++)
for(j=0;j<4;j++)
for(k=0;k<4;k++)
*(q+4*i+j)=*(q+4*i+j)+(*(a+4*i+k))*(*(b+4*k+j));
}

void main()
{
clrscr();
double A[4][4],B[4][4],D[4][4],C[4][4],L[4][4] ;
int i,j,k,l,n,m;
randomize();
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
{
A[i][j]=random(10);
D[i][j]=0;
cout <<" "<<A[i][j];
}cout<<endl;
}
cout<<" "<<endl;
for(k=0;k<4;k++)
{
for(l=0;l<4;l++)
{
B[k][l]=random(10);
cout<<" "<<B[k][l];
}cout<<endl;
}
mult(A[0],B[0],D[0]);
cout<<"matrica D[4][4]=A[4][4]*B[4][4] :"<<endl;
for(i=0;i<4;i++)
for(j=0;j<4;j++)
cout<<""<<D[i][j]<<endl;
//cout <<D[4][4];//
for(n=0;n<4;n++)
{
for(m=0;m<4;m++)
{
C[n][m]=random(10);
L[i][j]=0;
cout<<""<<C[n][m];
}cout<<endl;
}
cout<<" "<<endl;
mult(D[0],C[0],L[0]);
cout<<"matrica L[4][4]=C[4][4]*D[4][4] :"<<endl;
for(i=0;i<4;i++)
for(j=0;j<4;j++)
cout<<""<<L[i][j]<<endl;
getch();
}

30 ответов в теме “Возведение матрицы в степень на С++”

  1. 14
    Кирилл Быков ответил:

    Мне, почему-то, тоже пришла в голову такая мысль… ещё вчера :)

  2. 13
    Леонид Максимов ответил:

    peace :)

    на самом деле, я полагаю, Юлечка уже месяц как сдала свою программу

  3. 12
    Кирилл Быков ответил:

    Оптимизация — вещь хорошая. А вдруг скорость важна? Почему я не могу посоветовать? А потом Юля пусть сама решает, пользоваться ей моим советом или нет.

  4. 11
    Леонид Максимов ответил:

    вот и я про то же. зачем усложнять жизнь студентам оптимизациями, которые с них не спрашивают?

  5. 10
    Кирилл Быков ответил:

    По условию число натуральное. Зачем усложнять себе жизнь? К тому же можно, если захотеть, алгоритм доработать с учётом вещественного показателя. Главное, я идею привёл с оптимизацией. А от неё уже можно плясать куда хош. Кроме того, для заданного условия этой идеи полностью достаточно.

  6. 9
    Леонид Максимов ответил:

    конечно бывает. например извлечение квадратного корня: какую матрицу нужно умножить саму на себя, чтобы получить данную?

  7. 8
    Кирилл Быков ответил:

    А такое бывает разве? А кроме того, разве до меня в этой теме кто-нибудь предлагал алгоритм такой с нецелой степенью? Покажите мен пальчиком где, а то я сам что-то не нашёл… :-/

  8. 7
    Леонид Максимов ответил:

    а как насчет возведения матрицы в нецелую степень?

  9. 6
    Кирилл Быков ответил:

    Быстрое возведение в целую степень
    double pow(double b, int d)
    {
    double r=1;
    while (d>0)
    {
    if (d&1) {r*=b;–d} else {d>>=1;b*=b}
    }
    return r;
    }

    Вместо double пишешь свой матричный тип, и умножения заменяешь.
    Если тупо d раз умножать, трудоёмкость=d*(сложность умножения матриц), а при быстрой степени — log(d)*(сложность умножения матриц).

  10. 5
    Кирилл Быков ответил:

    Естественно, для отрицательных d нужно делать отдельную ветку с нахождением обратной матрицы.

  11. 4
    Олег Давыдов ответил:

    Эмм… Вы, наверное, не знаете, что делает операция сложения указателя и числа. На sizeof() умножать не надо.

  12. 3
    Леонид Максимов ответил:

    не уверен, что в функции mult конструкция
    *(q+4*i+j)=*(q+4*i+j)+(*(a+4*i+k))*(*(b+4*k+j));
    будет работать вообще.

    правильный вариант выглядит примерно так:
    *(q+(4*i+j)*sizeof(*q))=*(q+(4*i+j)*sizeof(*q))+(*(a+(4*i+k)*sizeof(*a)))*(*(b+(4*k+j)*sizeof(*b)));

    а лучше как-нибудь так:
    q[4*i+j]=q[4*i+j]+a[4*i+k]*b[4*k+j];

    что, впрочем, как и принятие функцией многомерных массивов типа a[4][4], усложняет последующую поддержку кода.

  13. 2
    Олег Давыдов ответил:

    1) Я бы написал обнуление в функции mult, да и получала бы она не "double *a" а "doube a[4][4]", тогда можно было бы писать "a[i][j]" вместо "*(a+i*4+j)", и вызывалась бы как "mult(A,B,D)" вместо "mult(A[0],B[0],D[0])"

    2) Возведение в степень можно написать за O(logp) уможений матриц:
    double L[4][4]; // это то, что уже подсчитано
    double R[4][4]; // То, куда будем собирать ответ
    double T[4][4]; // Временная
    // сначала запишем в R единичнуюю матрицу
    for (i=0;i<4;i++) for (j=0;j<4;j++)
    R[i][j] = i == j ? 1 : 0;
    // Теперь умножаем
    for (; p > 0; p /= 2)
    {
    if (p % 2 == 1)
    {
    mult(L, R, T);
    memcpy(R, T, sizeof(R));
    }
    // Возводим L в квадрат
    mult(L, L, T);
    memcpy(L, T, sizeof(R));
    }

  14. 1
    Алексей Дарий ответил:

    Как-то жОстко ты с массивами и функциями работаешь… Ну, да не суть.

    Делаешь цикл от 1 до p и в нём вызываешь свою чудо-"функцию" mult:
    for(i=1; i<p; i++)
    {
    mult(L[0],temp[0], result[0]);
    temp = result;
    }
    result – твой искомый результат.

Клуб программистов работает уже ой-ой-ой сколько, а если поточнее, то с 2007 года.