У меня есть double a[50][50];
2D-массив, который я инициализирую с помощью значений с плавающей запятой меньше 1. После умножения матрицы 14-15 раз на себя, матрица остается неизменной.
Чтобы быть более конкретным, я обнаружил A^k
где A
- двумерная матрица. Значения матрицы перестают меняться после 14 умножений.
Как я могу предотвратить это? Я хочу выполнить матричные умножения при больших значениях k
,
1 <= k <= 10^9
.
#include <stdio.h>
#include <iostream>
#include <vector>
#include <algorithm>
#define ll long long
#define pb push_back
using namespace std;
std::vector<std::vector<double> > A(51, std::vector<double>(51));
void expo(long long t,int n){
if(t==1)
return;
std::vector<std::vector<double> > B(n+1, std::vector<double>(n+1));
if(t&1){
for(int x=0;x<n;x++)
for(int y=0;y<n;y++)
B[x][y]=A[x][y];
}
std::vector<std::vector<double> > C(n+1, std::vector<double>(n+1));
for(int x=0;x<n;x++)
for(int y=0;y<n;y++){
C[x][y]=0;
for(int z=0;z<n;z++){
C[x][y]=(C[x][y]+A[x][z]*A[z][y]);
}
}
for(int x=0;x<n;x++)
for(int y=0;y<n;y++)
A[x][y]=C[x][y];
expo(t>>1,n);
if(t&1){
for(int x=0;x<n;x++)
for(int y=0;y<n;y++){
C[x][y]=0;
for(int z=0;z<n;z++){
C[x][y]=(C[x][y]+A[x][z]*B[z][y]);
}
}
for(int x=0;x<n;x++)
for(int y=0;y<n;y++)
A[x][y]=C[x][y];
}
}
int main(){
int k;
cin>>k;
int ix,iy;
for(ix=0;ix<50;ix++)
for(iy=0;iy<50;iy++)
cin>>A[ix][iy];
expo(k,50);
for(int i=0;i<50;i++)
{
for(int j=0;j<50;j++)
{
cout<<A[i][j]<<" ";
}
cout<<"\n";
}
return 0;
}
РЕДАКТИРОВАТЬ:
Данная матрица является марковской матрицей.
Я заменил double a[50][50];
с std::vector<std::vector<double> > a(50, std::vector<double>(50));
(размер вектора может варьироваться)
Я верну свои комментарии в ответ:
Марковские (или стохастические) матрицы могут достигать устойчивого состояния, так что независимо от начального состояния состояние будет примерно одинаковым (т.е. устойчивым) после достаточного времени/итераций. Например (следующие слайды здесь):
После n
итераций получаем, что
Таким образом, любое начальное состояние (сумма элементов должно равняться 1) приведет к {2/3, 1/3}. При использовании чисел с плавающей запятой для представления значений матрицы изменение между итерацией n
и n+1
часто может быть меньше, чем ULP.
double B[n+1][n+1];
Это не разрешено C ++. Размеры массивов должны быть известны во время компиляции.A^k->A
особенно если вы используете конечные числа с плавающей запятой для ее представления.