Instantly share code, notes, and snippets.

# komasaru/calc.cpp

Last active Jul 31, 2020
C++ source code to calculate a simple regression curve(4d).
 #include "calc.hpp" #include #include #include /** * @brief 単回帰曲線（4次）の計算 * * @param[ref] a (double) * @param[ref] b (double) * @param[ref] c (double) * @param[ref] d (double) * @param[ref] e (double) * @return 真偽(bool) * @retval true 成功 * @retval false 失敗 */ bool Calc::reg_curve_4d(double& a, double& b, double& c, double& d, double& e) { unsigned int i; // loop インデックス double s_x = 0.0; // sum(x) double s_x2 = 0.0; // sum(xx) double s_x3 = 0.0; // sum(xxx) double s_x4 = 0.0; // sum(xxxx) double s_x5 = 0.0; // sum(xxxxx) double s_x6 = 0.0; // sum(xxxxxx) double s_x7 = 0.0; // sum(xxxxxxx) double s_x8 = 0.0; // sum(xxxxxxxx) double s_y = 0.0; // sum(y) double s_xy = 0.0; // sum(xy) double s_x2y = 0.0; // sum(xxy) double s_x3y = 0.0; // sum(xxxy) double s_x4y = 0.0; // sum(xxxxy) double x = 0.0; // x 計算用 double x2 = 0.0; // xx 計算用 double x3 = 0.0; // xxx 計算用 double x4 = 0.0; // xxxx 計算用 double x5 = 0.0; // xxxxx 計算用 double x6 = 0.0; // xxxxxx 計算用 double x7 = 0.0; // xxxxxxx 計算用 double x8 = 0.0; // xxxxxxxx 計算用 double y = 0.0; // y 計算用 try { // データ数 cnt = data.size(); // sum(x), sum(xx), sum(xxx), sum(xxxx), sum(xxxxx), // sum(xxxxxx), sum(xxxxxxx), sum(xxxxxxxx), // sum(y), sum(xx), sum(xy), sum(x2y), sum(x3y), sum(x4y) for (i = 0; i < cnt; i++) { x = data[i][0]; y = data[i][1]; x2 = x * x; x3 = x2 * x; x4 = x3 * x; x5 = x4 * x; x6 = x5 * x; x7 = x6 * x; x8 = x7 * x; s_x += x; s_x2 += x2; s_x3 += x3; s_x4 += x4; s_x5 += x5; s_x6 += x6; s_x7 += x7; s_x8 += x8; s_y += y; s_xy += x * y; s_x2y += x2 * y; s_x3y += x3 * y; s_x4y += x4 * y; } // 行列1行目 mtx.push_back({(double)cnt, s_x, s_x2, s_x3, s_x4, s_y}); // 行列2行目 mtx.push_back({s_x, s_x2, s_x3, s_x4, s_x5, s_xy}); // 行列3行目 mtx.push_back({s_x2, s_x3, s_x4, s_x5, s_x6, s_x2y}); // 行列4行目 mtx.push_back({s_x3, s_x4, s_x5, s_x6, s_x7, s_x3y}); // 行列5行目 mtx.push_back({s_x4, s_x5, s_x6, s_x7, s_x8, s_x4y}); // 計算（ガウスの消去法） if (!solve_ge(mtx)) { std::cout << "[ERROR] Failed to solve by the Gauss-Ellimination method!" << std::endl; return false; } // a, b, c, d, e a = mtx[0][5]; b = mtx[1][5]; c = mtx[2][5]; d = mtx[3][5]; e = mtx[4][5]; } catch (...) { return false; // 計算失敗 } return true; // 計算成功 } /** * @brief ガウスの消去法 * * @param[ref] 行列（配列） mtx (double) * @return 真偽(bool) * @retval true 成功 * @retval false 失敗 */ bool Calc::solve_ge(std::vector>& mtx) { int i; // loop インデックス int j; // loop インデックス int k; // loop インデックス int n; // 元（行）の数 double d; // 計算用 try { n = (int)mtx.size(); // 前進消去 for (k = 0; k < n - 1; k++) { for (i = k + 1; i < n; i++) { d = mtx[i][k] / mtx[k][k]; for (j = k + 1; j <= n; j++) mtx[i][j] -= mtx[k][j] * d; } } // 後退代入 for (i = n - 1; i >= 0; i--) { d = mtx[i][n]; for (j = i + 1; j < n; j++) d -= mtx[i][j] * mtx[j][n]; mtx[i][n] = d / mtx[i][i]; } } catch (...) { return false; // 計算失敗 } return true; // 計算成功 }
 #ifndef REGRESSION_CURVE_4D_CALC_HPP_ #define REGRESSION_CURVE_4D_CALC_HPP_ #include class Calc { std::vector> data; // 元データ std::vector> mtx; // 計算用行列 bool solve_ge(std::vector>&); // ガウスの消去法 public: Calc(std::vector>& data) : data(data) {} unsigned int cnt; // データ件数 bool reg_curve_4d(double&, double&, double&, double&, double&); // 単回帰曲線（4次）の計算 }; #endif
 #include "file.hpp" #include #include #include #include bool File::get_text(std::vector>& data) { try { // ファイル OPEN std::ifstream ifs(f_data); if (!ifs.is_open()) return false; // 読み込み失敗 // ファイル READ std::string buf; // 1行分バッファ while (getline(ifs, buf)) { std::vector rec; // 1行分ベクタ std::istringstream iss(buf); // 文字列ストリーム std::string field; // 1列分文字列 // 1行分文字列を1行分ベクタに追加 double x, y; while (iss >> x >> y) { rec.push_back(x); rec.push_back(y); } // １行分ベクタを data ベクタに追加 if (rec.size() != 0) data.push_back(rec); } } catch (...) { std::cerr << "EXCEPTION!" << std::endl; return false; } return true; // 読み込み成功 }
 #ifndef REGRESSION_CURVE_4D_FILE_HPP_ #define REGRESSION_CURVE_4D_FILE_HPP_ #include #include #include class File { std::string f_data; public: File(std::string f_data) : f_data(f_data) {} bool get_text(std::vector>&); }; #endif
 /*********************************************************** 単回帰曲線（4次回帰モデル）計算 : y = a + b * x + c * x^2 + d * x^3 + e * x^4 : 連立方程式をガウスの消去法で解く方法 DATE AUTHOR VERSION 2020.05.19 mk-mode.com 1.00 新規作成 Copyright(C) 2020 mk-mode.com All Rights Reserved. ***********************************************************/ #include "calc.hpp" #include "file.hpp" #include // for EXIT_XXXX #include // for setprecision #include #include #include int main(int argc, char* argv[]) { std::string f_data; // データファイル名 std::vector> data; // データ配列 std::size_t i; // loop インデックス double a; // 定数 a double b; // 係数 b double c; // 係数 c double d; // 係数 d double e; // 係数 e try { // コマンドライン引数のチェック if (argc != 2) { std::cerr << "[ERROR] Number of arguments is wrong!\n" << "[USAGE] ./regression_curve_4d " << std::endl; return EXIT_FAILURE; } // ファイル名取得 f_data = argv[1]; // データ取得 File file(f_data); if (!file.get_text(data)) { std::cout << "[ERROR] Failed to read the file!" << std::endl; return EXIT_FAILURE; } // データ一覧出力 std::cout << std::fixed << std::setprecision(4); std::cout << "説明変数 X 目的変数 Y" << std::endl; for (i = 0; i < data.size(); i++) std::cout << std::setw(10) << std::right << data[i][0] << " " << std::setw(10) << std::right << data[i][1] << std::endl; // 計算 Calc calc(data); if (!calc.reg_curve_4d(a, b, c, d, e)) { std::cout << "[ERROR] Failed to calculate!" << std::endl; return EXIT_FAILURE; } // 結果出力 std::cout << std::fixed << std::setprecision(8); std::cout << "---\n" << "a = " << std::setw(16) << std::right << a << "\n" << "b = " << std::setw(16) << std::right << b << "\n" << "c = " << std::setw(16) << std::right << c << "\n" << "d = " << std::setw(16) << std::right << d << "\n" << "e = " << std::setw(16) << std::right << e << std::endl; } catch (...) { std::cerr << "EXCEPTION!" << std::endl; return EXIT_FAILURE; } return EXIT_SUCCESS; }