# 高斯消去
> 所有分母為 0 的輸入都會強制轉換成分母為 1
> 目前只能計算只有一組解的線性方程
> 分數「y分之x」以「x/y」表示 (例如:2分之3 -> 3/2)
## Main
```cpp=
#include <iostream>
#include "ELEMENT.h"
using namespace std;
//output matrix
template<class T>void print(string str, T *arr, const unsigned& sz);
template<class T>void print(string str, T **arr, const unsigned& _i, const unsigned& _j);
template<class T>void print(string str, T ***arr, const unsigned& _i, const unsigned& _j, const unsigned& _k);
class Gaussian_Elimination {
private:
unsigned D; //矩陣大小(以係數方陣為主)
Element*** CP; //紀錄矩陣在消去時的過程
Element** matrix; //矩陣內容
Element* r; //線性方程之根
public:
inline void New_All(); //宣告陣列大小
inline void Delete_All(); //移除陣列
inline void Input(); //輸入
inline void Update_CP(const int& k); //更新目前的計算過程
inline void Elimination(); //高斯消去
inline void Get_Roots(); //取得線性方程之根
inline void Solve(); //類 int main()
};
//--------------------------- Main ---------------------------
int main() {
Gaussian_Elimination GE;
GE.Solve();
return 0;
}
// --------------------------- class Gaussian_Elimination ---------------------------
inline void Gaussian_Elimination::New_All() {
CP = new Element * *[D] {0};
matrix = new Element * [D];
r = new Element[D];
for (unsigned i = 0; i < D; i++) {
CP[i] = new Element * [D + 1]{ 0 };
matrix[i] = new Element[D + 1];
for (unsigned j = 0; j < D + 1; j++) {
CP[i][j] = new Element[D - 1]{ 0 };
}
}
}
inline void Gaussian_Elimination::Delete_All() {
for (unsigned i = 0; i < D; i++) {
for (unsigned j = 0; j < D + 1; j++) {
delete[] CP[i][j];
}
delete[] CP[i]; delete[] matrix[i];
}
delete[] CP; delete[] matrix; delete[] r;
}
inline void Gaussian_Elimination::Input() {
cout << "Input the size of Coefficient Matrix:\n";
cin >> D;
cout << "Input your Augmented Matrix:\n";
New_All();
for (unsigned i = 0; i < D; i++) {
for (unsigned j = 0; j < D + 1; j++) {
cin >> matrix[i][j];
}
}
}
inline void Gaussian_Elimination::Update_CP(const int& k) {
for (unsigned i = 0; i < D; i++) {
for (unsigned j = 0; j < D + 1; j++) {
CP[i][j][k] = matrix[i][j];
}
}
}
inline void Gaussian_Elimination::Elimination() {
for (unsigned R = 0; R < D - 1; R++) {
for (unsigned i = R + 1; i < D; i++) {
Element A = matrix[i][R], B = matrix[R][R], C;
C = A / B;
for (unsigned j = R; j < D + 1; j++) {
Element T = matrix[R][j];
matrix[i][j] = matrix[i][j] - T * C;
}
}
Update_CP(R);
}
}
inline void Gaussian_Elimination::Get_Roots() {
for (int i = int(D) - 1; i >= 0; i--) {
Element tmp = matrix[i][D];
for (int j = int(D) - 1; j > i; j--) {
tmp = tmp - r[j] * matrix[i][j];
}
r[i] = tmp / matrix[i][i];
}
}
inline void Gaussian_Elimination::Solve() {
Input();
Elimination();
print("\nCalculation:", matrix, D, D + 1);
Get_Roots();
print("\nRoots:", r, D);
print("\nComputational Process:", CP, D, D + 1, D - 1);
Delete_All();
}
template<class T>
void print(string str, T *arr, const unsigned& sz) {
cout << str << '\n';
for (unsigned i = 0; i < sz; i++) {
cout << arr[i] << " ";
}
cout << '\n';
}
template<class T>
void print(string str, T **arr, const unsigned& _i, const unsigned& _j) {
cout << str << '\n';
for (unsigned i = 0; i < _i; i++) {
for (unsigned j = 0; j < _j; j++) {
cout << arr[i][j] << " ";
}
cout << '\n';
}
}
template<class T>
void print(string str, T ***arr, const unsigned& _i, const unsigned& _j, const unsigned& _k) {
cout << str << '\n';
for (unsigned k = 0; k < _k; k++) {
cout << '\n';
for (unsigned i = 0; i < _i; i++) {
for (unsigned j = 0; j < _j; j++) {
cout << arr[i][j][k] << " ";
}
cout << '\n';
}
}
}
```
## "ELEMENT.h"
```cpp=
//ELEMENT.h
#ifdef ELEMENT
#define ELEMENT __declspec(dllexport)
#else
#define ELEMENT __declspec(dllimport)
#endif
#include <iostream>
#include <algorithm>
using namespace std;
class ELEMENT Element{
public:
Element():
numerator(0), denominator(1), interger(true){}
Element(const int &X):
numerator(X), denominator(1), interger(true){}
Element(const int &X, const int &Y):
numerator(X), denominator(Y){
simplify();
}
inline Element operator*(const Element& X); //重載運算子「*」
inline Element operator/(const Element& X); //重載運算子「/」
inline Element operator+(const Element& X); //重載運算子「+」
inline Element operator-(const Element& X); //重載運算子「-」
inline void operator=(const Element& X); //重載運算子「=」
inline bool operator==(const Element& X); //重載運算子「==」
friend ostream& operator<<(ostream& output, const Element& X); //重載運算子「<<」
friend istream& operator>>(istream& input, Element& X); //重載運算子「>>」
private:
int numerator, denominator; //分子;分母
bool interger;
int __lcm(const int &a, const int &b){ return a * b / __gcd(a, b); }
inline void simplify(){ //簡化分數
if (denominator != 1){
int r = __gcd(numerator, denominator);
numerator /= r, denominator /= r;
}
if(denominator < 0){
numerator *= -1, denominator *= -1;
}
interger = (denominator == 1 or denominator == -1 ? true : false);
}
};
inline Element Element::operator*(const Element& X){
Element tmp(numerator * X.numerator, denominator * X.denominator);
tmp.simplify();
return tmp;
};
inline Element Element::operator/(const Element& X){
Element tmp(numerator * X.denominator, denominator * X.numerator);
tmp.simplify();
return tmp;
};
inline Element Element::operator+(const Element& X){
Element tmp(0, 1);
tmp.denominator = __lcm(denominator, X.denominator);;
tmp.numerator = tmp.denominator / denominator * numerator +
tmp.denominator / X.denominator * X.numerator;
tmp.simplify();
return tmp;
};
inline Element Element::operator-(const Element& X){
Element tmp(0, 1);
tmp.denominator = __lcm(denominator, X.denominator);;
tmp.numerator = tmp.denominator / denominator * numerator -
tmp.denominator / X.denominator * X.numerator;
tmp.simplify();
return tmp;
};
inline void Element::operator=(const Element& X){
this->numerator = X.numerator, this->denominator = X.denominator;
simplify();
}
inline bool Element::operator==(const Element& X){
return numerator == X.numerator and denominator == X.denominator;
};
inline ostream& operator<<(ostream& output, const Element& X){
if (X.interger)output << X.numerator;
else output << X.numerator << '/' << X.denominator;
return output;
}
inline istream& operator>>(istream& input, Element& X){
string str; input >> str;
int x = 0, y = 0,
negative = (str[0] == '-' ? -1 : 1);
bool gate = true;
for (unsigned i = 0; i < str.size(); i++){
if (str[i] == '/'){ gate = false; }
else if (str[i] >= '0' and str[i] <= '9'){
if (gate)x = x * 10 + str[i] - '0';
else y = y * 10 + str[i] - '0';
}
}
X.numerator = x * negative;
X.denominator = (y == 0 ? 1 : y);
return input;
}
```