创建博客 登录  
 加关注
   显示下一条  |  关闭

(((silence)))

#define if(...) if(!(__VA_ARGS__))

 
 
 

日志

 
 

期末实现了一坨C++数值算法[4] 高斯消去法  

2009-12-30 11:58:36|  分类: 编程 |  标签: |字号 订阅

算法描述

1 高斯消去法基本思路。

设有方程组Ax=b,设A是可逆矩阵。高斯消去法的基本思想就是僵局真的初等行变换作用于方程组的增广矩阵wps_clip_image-147,将其中的A变换成一个上三角矩阵,然后求解这个三角形方程组。

2 列主元高斯消去法计算步骤

将方程组用增广矩阵wps_clip_image-258表示。

步骤1:消元过程,对k=1,2,…,n-1

(1) 选主元,找wps_clip_image-332使得

wps_clip_image-362

(2) 如果ai,j=0,则矩阵A奇异,程序结束;否则执行(3)。

(3) 如果wps_clip_image-469,则交换第k行与第ik行对应元素位置,wps_clip_image-566,j=k,…,n+1。

(4) 消元,对i=k,…n,计算wps_clip_image-657对j=k+1,…,n+1,计算

aij=aij-likakj

步骤 2:回代过程:

(1) 若ann=0,则矩阵奇异,程序结束;否则执行(2)。

xn=an,n+1/ann对i=n-1,…,2,1,计算wps_clip_image-861

 

===== 上面还是抄的,感觉还是 wikipedia 说得比较好 =====

======= 下面是我的实现 =====

// 列选主元

// 依赖项:向量和矩阵类

 

bool gaussianBackSubstitution(NA::MatDP& m, NA::MatDP& b)
    // 有回代过程的高斯消元法
    // 参数:
    //   m: N x N 的系数矩阵
    //   b: A x N 的右端向量矩阵
    // 返回值:
    //   是否有解
    // 返回时 m 和 b 都已被破坏
    // m 是消去之后的矩阵
    // b 是解向量
{
    if (m.rows()!=m.cols()) {
        return false;
    }
    if (m.rows()!=b.rows()) {
        return false;
    }
    const int n_row=m.rows();
    const double eps=1.0e-10;
    double row_bigest=0, tmp;
    int   i,j,k,nth;

    // 向下消去,过程与高斯-若当方法相同
    for( i=0; i<n_row-1; ++i) {
        row_bigest=0;
        // 选取主元 {{{
        for( j=i; j<n_row; ++j) {
            if(row_bigest<(tmp=fabs(m[j][i]))) {
                row_bigest=tmp;
                nth=j;
            }
        }
        if(fabs(row_bigest)<eps)
            return false;
        if(nth>i){
            m.swapRow(i,nth);
            b.swapRow(i,nth);
        }
        // }}}
        // 消去
        for( j=i+1; j<n_row; ++j) {
            tmp=m[j][i]/m[i][i];
            m[j][i]=0.0;
            for( k=i+1; k<n_row; ++k )
                m[j][k]-=m[i][k]*tmp;
            for( k=0; k<b.cols(); ++k )
                b[j][k]-=b[i][k]*tmp;
        }
    }

    // 回代过程
    for( i=0; i<b.cols(); ++i ) { // 一次可以解出一组方程
        for( j=b.rows()-1; j>=0; --j ) {
            for( k=j+1; k<b.rows(); ++k )
                b[j][i]-=b[k][i]*m[j][k]; // 将已算出的结果(b[k][i])带入
            b[j][i]/=m[j][j];
        }
    }
    return true;
}

 

// 顺便,还有高斯-若当消去法:

bool gaussianJordan(NA::MatDP& m, NA::MatDP& b)
    // 高斯-若当 消去法
    // 参数:
    //   m: N x N 的系数矩阵
    //   b: A x N 的右端向量矩阵
    // 返回值:
    //   是否有解
    // 返回时 m 和 b 都已被破坏
    // m 是消去之后的矩阵
    // b 是解向量
{
    if (m.rows()!=m.cols()) {
        return false;
    }
    if (m.rows()!=b.rows()) {
        return false;
    }
    const int n_row=m.rows();
    const double eps=1.0e-10;
    double row_bigest=0, tmp;
    int   i,j,k,nth;

    // 向下消去
    for( i=0; i<n_row-1; ++i) {
        row_bigest=0;
        // 选取主元 {{{
        for( j=i; j<n_row; ++j) {
            if(row_bigest<(tmp=fabs(m[j][i]))) {
                row_bigest=tmp;
                nth=j;
            }
        }
        if(fabs(row_bigest)<eps)
            return false;
        if(nth>i){
            m.swapRow(i,nth);
            b.swapRow(i,nth);
        }
        // }}}
        // 消去
        for( j=i+1; j<n_row; ++j) {
            tmp=m[j][i]/m[i][i];
            m[j][i]=0.0;
            for( k=i+1; k<n_row; ++k )
                m[j][k]-=m[i][k]*tmp;
            for( k=0; k<b.cols(); ++k )
                b[j][k]-=b[i][k]*tmp;
        }
    }

    // 向上消去
    for( i=n_row-1; i>=0; --i ) {
        tmp=m[i][i];
        if(fabs(tmp)<eps)
            return false;
        m[i][i]=1.0;
        for( j=i+1; j<n_row; ++j ) {
            m[i][j] /= tmp;
        }
        for( j=0; j<b.cols(); ++j ) {
            b[i][j] /= tmp;
        }
        for( j=i-1; j>=0; --j ) {
            tmp=m[j][i];
            m[j][i]=0.0;
            for( k=i+1; k<n_row; ++k ) {
                m[j][k]-=m[i][k]*tmp;
                if(fabs(m[j][k])<eps)
                    m[j][k]=0.0;
            }
            for( k=0; k<b.cols(); ++k ) {
                b[j][k]-=b[i][k]*tmp;
                if(fabs(b[j][k])<eps)
                    b[j][k]=0.0;
            }
        }
    }

    return true;
}

 

 

OVER

  评论这张
转发至微博
转发至微博
0   分享到:        
阅读(866)| 评论(2)| 不可引用 |举报
<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--相关文章--> <#--历史上的今天--> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2012