使用 C++ 程序求 21by21 矩阵行列式的问题

问题描述 投票:0回答:1

我一直在使用 C++ 程序来计算 nbyn 的行列式 方阵。它适用于较低的订单(我得到了 n=6 的精确结果)。我需要计算 21by21 矩阵的行列式,但程序需要无限的时间来计算行列式。

我正在写下我使用的代码:

# include<iostream>
# include<fstream>
# include<cmath>
   
using namespace std;
float determinant( float matrix2[21][21], int n2)
{
    float det = 0;
    float submatrix2[21][21];
    if (n2 == 2)
        return ((matrix2[1][1] * matrix2[0][0]) - (matrix2[0][1] * matrix2[1][0]));
    else {
        for (int l = 0; l < n2; l++) {
            int subi = 0;
            for (int m = 1; m < n2; m++) {
                int  subj = 0;
                for (int p = 0; p < n2; p++) {
                    if (p == l)
                        continue;
                    submatrix2[subi][subj] = matrix2[m][p];
                    subj++;
                }
                subi++;
            }
            det = det + (pow(-1, l) * matrix2[0][l] * determinant( submatrix2, n2 - 1 ));
        }
    }
    return det;
}

int main()
{
    ifstream aa("matrix21.dat");
    float a[21][21];
    int p,q;
    for(p=0;p<21;p++)
    {
        for(q=0;q<21;q++)
        {
            aa>>a[p][q];
        }
    }
    for(p=0;p<21;p++)
    {
        for(q=0;q<21;q++)
        {
            cout<<a[p][q]<<"  ";
        }
        cout<<endl;
    }
    float det;
    det=determinant(a,21);
    cout<<"The determinant is :"<<det<<endl;
    return(0);
}

即使我尝试在输入文件中给出对角矩阵,但程序无法提供结果。

c++ sparse-matrix determinants
1个回答
0
投票

如果你尝试在未成年人中使用扩展,那么 21 个未成年人将分别触发 20 个未成年人的扩展,这将分别触发 19 个未成年人的扩展,......等等。即使有一些明智的记忆,这也是站不住脚的。

相反,您可以执行高斯消去法的步骤,将矩阵简化为上三角形式。一旦主对角线下方有零,那么行列式就是对角线元素的乘积。

请注意,部分旋转(交换行以将最大可能的元素放置在枢轴位置)通常对于数值稳定性是可取的。每行交换都会将行列式的符号更改 -1。

请注意,21x21 矩阵可能具有相当大的行列式;注意溢出。

这是一个 C++ 代码及其 21x21 矩阵的输出(在底部给出)。确保您的代码知道它期望从文件中读取多大的矩阵。

我用Python检查了它(通过作弊并使用numpy.linalg库)。

c++代码

#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;

const double SMALL = 1.0E-30;

using matrix = vector< vector<double> >;

//======================================================================

matrix readMatrix( int N, string filename )      // It is assumed you know how big your matrix is!
{
   matrix M( N, vector<double>( N ) );
   ifstream in( filename );
   for ( int i = 0; i < N; i++ )
   {
      for ( int j = 0; j < N; j++ ) in >> M[i][j];
   }
   return M;
}

//======================================================================

double determinant( matrix A )
{
   int n = A.size();
   double det = 1;

   // Reduce to row-echelon form by pivoting from rows i = 0, ,,,, n - 2 (n-1 not needed)
   // Better numerics by swapping rows to put largest possible element as pivot
   // The determinant changes sign when you swap rows, so keep a tally!
   // After reduction to RE form, the determinant is just the product of the diagonal elements

   for ( int i = 0; i < n - 1; i++ )
   {
      // Partial pivot: find row r below with largest element in column i
      int r = i;
      double maxA = abs( A[i][i] );
      for ( int k = i + 1; k < n; k++ )
      {
         double val = abs( A[k][i] );
         if ( val > maxA )
         {
            r = k;
            maxA = val;
         }
      }
      if ( r != i )
      {
         for ( int j = i; j < n; j++ ) swap( A[i][j], A[r][j] );
         det = -det;                                       // Swap rows - flip sign of determinant
      }

      // Row operations to make upper-triangular
      double pivot = A[i][i];
      if ( abs( pivot ) < SMALL ) return 0.0;              // Singular matrix

      for ( int r = i + 1; r < n; r++ )                    // Remove multiples from lower rows
      {
         double multiple = A[r][i] / pivot;                // Multiple of row i to clear element in ith column below
         for ( int j = i; j < n; j++ ) A[r][j] -= multiple * A[i][j];
      }
      det *= pivot;                                        // Determinant is product of diagonal elements
   }

   det *= A[n-1][n-1];

   return det;
}

//======================================================================

int main()
{
   matrix M = readMatrix( 21, "matrix.dat" );
   cout << "determinant = " << determinant( M ) << '\n';
}

//======================================================================

样本矩阵的输出(如下):

determinant = -0.0178605

Python 库代码(待检查):

import numpy as np
M = np.loadtxt( "matrix.dat" )
print( np.linalg.det( M ) )

样本矩阵的输出(如下):

-0.017860521764216902

示例 21x21 矩阵(使用下面的生成器随机生成):

 0.72  0.11  0.79  0.51  0.51  0.85   0.4  0.75  0.44  0.03  0.95  0.03  0.65  0.21  0.95   0.2  0.16  0.86   0.2  0.17  0.75 
 0.38  0.74  0.73  0.06  0.07  0.56  0.83  0.11  0.78  0.66  0.19  0.32   0.7  0.28  0.73   0.3  0.06  0.12  0.04  0.25  0.47 
 0.34   0.8  0.53  0.28  0.61  0.54  0.35  0.65  0.81  0.19  0.86  0.09  0.14  0.96  0.39  0.84  0.92   0.7  0.95  0.84  0.37 
 0.06  0.36  0.44  0.35   0.9  0.47  0.57  0.22  0.79  0.48  0.59   0.2  0.18   0.1  0.84   0.4  0.78  0.05  0.67  0.19  0.92 
 0.53  0.88  0.49  0.95   0.1  0.73  0.27  0.93  0.36  0.36  0.73  0.81  0.71  0.95  0.67  0.61  0.07  0.48  0.76  0.79  0.68 
 0.31   0.1  0.04  0.42  0.65  0.23  0.72  0.11   0.3  0.43  0.32  0.37  0.45  0.52  0.73  0.53  0.54  0.78  0.24  0.48   0.6 
 0.54  0.71  0.86  0.69  0.09  0.91  0.28   0.5  0.81  0.38  0.38  0.31  0.16  0.63  0.64  0.15  0.08  0.07  0.64  0.76  0.81 
 0.14  0.13  0.54  0.96  0.31  0.02  0.23  0.49  0.44  0.83  0.82   0.6  0.26  0.55  0.96  0.33  0.55  0.05  0.03   0.8  0.53 
 0.69  0.15  0.02  0.26  0.73   0.1  0.25  0.44  0.04  0.39  0.49  0.51  0.29  0.85  0.64  0.56  0.85  0.25  0.31  0.05  0.75 
 0.28  0.43  0.18  0.52  0.54  0.63  0.38  0.47  0.08  0.54  0.03  0.01  0.52  0.19  0.34  0.71   0.9  0.11  0.34  0.68  0.41 
 0.47   0.3  0.18  0.76  0.35  0.61  0.89  0.86  0.02  0.66  0.38   0.2  0.86  0.12  0.09  0.69  0.79  0.64  0.36  0.03  0.87 
 0.64  0.06  0.92  0.37  0.34  0.13  0.95  0.38   0.9  0.51  0.48  0.31  0.12  0.19  0.94  0.28  0.82  0.62  0.83  0.24  0.96 
 0.92  0.17  0.83  0.64  0.52  0.51  0.08  0.64  0.38  0.21  0.99  0.02  0.45  0.37  0.78  0.79  0.24  0.98  0.14  0.75  0.13 
 0.46   0.4     0  0.84  0.74  0.32  0.78  0.84  0.41  0.82  0.34  0.39  0.71  0.92  0.17  0.07  0.23  0.39  0.11  0.93  0.98 
 0.45  0.38  0.45  0.69  0.55  0.33  0.46  0.69  0.82  0.82  0.07  0.98  0.03  0.03  0.78   0.5  0.71  0.01   0.6  0.66  0.44 
 0.29  0.25   0.7   0.1  0.08  0.53   0.6   0.4  0.84  0.56  0.67  0.87  0.19  0.58  0.54  0.95  0.63   0.3  0.45  0.59  0.91 
  0.8   0.2     0  0.37  0.76  0.21  0.41  0.92  0.25  0.16   0.7  0.72  0.41  0.01  0.36  0.64  0.39  0.52  0.03  0.04  0.55 
 0.58  0.19  0.47  0.33  0.38  0.16  0.78  0.72  0.63   0.3  0.41   0.4  0.76  0.99  0.93  0.98  0.83  0.06  0.83  0.39  0.94 
 0.31  0.92  0.56  0.82   0.4  0.34  0.04  0.02  0.04   0.3  0.34  0.37  0.42  0.18  0.45  0.19   0.2  0.97  0.81  0.89  0.44 
 0.29  0.27  0.46   0.2  0.36  0.08  0.36  0.97  0.97  0.94  0.55  0.61  0.93  0.16  0.32   0.6  0.62  0.48  0.66  0.39  0.99 
 0.82  0.98  0.24  0.81  0.34   0.4  0.65  0.09  0.76  0.93  0.32  0.38  0.38   0.9  0.34  0.69  0.19  0.08  0.55  0.15  0.75 

简单矩阵生成器:

#include <iostream>
#include <iomanip>
#include <fstream>
#include <cstdlib>
#include <ctime>
using namespace std;

int main()
{
   const int N = 21;
   srand( time( 0 ) );
   ofstream out( "matrix.dat" );
   for ( int i = 0; i < N; i++ )
   {
      for ( int j = 0; j < N; j++ ) out << setw( 5 ) << 0.01 * ( rand() % 100) << " ";
      out << '\n';
   }
}
© www.soinside.com 2019 - 2024. All rights reserved.