2020-08-14

/*

高斯消元解線性方程組
X25XD~YZRE64YKBFU{4~F3X.png

1、C++在存儲浮點數(shù)時會存在誤差 當判斷一個浮點數(shù)是否為0時,不判斷==0
而是判斷是否小于eps 一個很小的數(shù)
2、舊版c++中 abs 返回整數(shù)的絕對值 fabs()返回浮點數(shù)的絕對值

高斯消元核心操作
1、枚舉每一列
2、找到當前這一列中絕對值最大的一行
3、將這行換到最上面去
4、將該行的第一個數(shù)變成1
5、將當前列的下面所有數(shù)消成0

*/

#include<bits/stdc++.h>
using namespace std;
const int N = 110;
const double eps = 1e-6;
int n;
double a[N][N];
void out() {
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n + 1; j++) {
            cout << a[i][j] << ' ';
        }
        cout << endl;
    }
    cout << endl;
}
int gauss()
{
    int c, r;
    for (c = 1, r = 1; c <= n; c++) {//操作1 按列枚舉 1~n
        int t = r;
        for (int i = r; i <= n; i++) { //操作2,找出當前枚舉列中的絕對值最大的行
            if (fabs(a[i][c]) > fabs(a[t][c]))
                t = i;        //C++存浮點數(shù)0時 可能存的是0.000001;
        }                   //C++在存入浮點數(shù)時有誤差,所以當他小于一個很小的數(shù)是認為他為0
        if (fabs(a[t][c]) < eps)//如果絕對值最大的數(shù)都是0,那么為全0列 不做操作
            continue;
        //將絕對值最大的那一行換到還沒確定的最上面一行
        //比如第一次操作完畢后第一行會被確定,以后就不動了
        //r++后便從第二行開始 在交換就把絕對值最大的一行和第二行交換
        for (int i = c; i <= n + 1; i++)swap(a[t][i], a[r][i]);
        //將最頂上這一行的第一個非0數(shù)字化為1
        //由于每次除以第一個數(shù)字,如果從前往后除,那么第一個數(shù)除完就變成1了
        //所以本步操作從后往前
        for (int i = n + 1; i >= c; i--)a[r][i] /= a[r][c];
        //將1下面的數(shù)字都化為0
        //每行成比例進行加減
        for (int i = r + 1; i <= n; i++) {
            //如果下面一行已經(jīng)是0,則不做操作
            if (fabs(a[i][c]) > eps) {
                //同理本步為倒敘操作,因為第一行第一個數(shù)已經(jīng)為1 這時候a[i][c](每行的第一個數(shù)就是比例)
                for (int j = n + 1; j >= c; j--) {
                    a[i][j] -= a[r][j] * a[i][c];
                }
            }
        }
        //操作完后 確定行數(shù)++
        r++;
        // out();
    }
    //這里r<=n由于r的初始值就為1 當r=n+1時才證明每一行都確定了
    if (r <= n) {
        //這里i=r 確定了兩行時r=3,所以r就是已經(jīng)確定的下一行了
        for (int i = r; i <= n; i++) {
            //如果出現(xiàn)0=!0的情況則無解
            if (fabs(a[i][n + 1]) > eps)
                return 2;
        }
        //否則出現(xiàn)的是0=0的情況為有無窮多個解
        return 1;
    }
    //倒敘求解
    //i從最后一行開始 逐個往上走
    //j為i+一列 如i=n-1,則n-1列的數(shù)為1 n-1列前的都為0 要把第n列的比例在n+1列減掉 
    //比例為a[i][j]
    for (int i = n; i >= 1; i--) {
        for (int j = i + 1; j <= n; j++) {
            a[i][n + 1] -= a[j][n + 1] * a[i][j];
        }

    }
    return 0;
}
int main()
{
    cin >> n;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n + 1; j++)
            cin >> a[i][j];
    }
    int t = gauss();
    if (t == 0) {
        for (int i = 1; i <= n; i++) {
            printf("%.2lf\n", a[i][n + 1]); //注意輸出兩位小數(shù)的寫法 %.2lf
        }
    }
    else if (t == 1)
        cout << "Infinite group solutions" << endl;
    else cout << "No solution" << endl;
    return 0;
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容