同様の関数を作成する必要がありましたが、垂直に近い斜面を処理するために必要でした。Cassio Neri のコードから始めて、x=y の線の周りの各ポイントをミラーリングした後、1 よりも急なように見える勾配を再計算するように修正しました (x と y の値を切り替えることで簡単に実行できます)。次に、それをミラーリングして、より正確な勾配を返します。
#include <algorithm>
#include <iostream>
#include <numeric>
#include <vector>
double slope(const std::vector<double>& x, const std::vector<double>& y) {
const double n = x.size();
const double s_x = std::accumulate(x.begin(), x.end(), 0.0);
const double s_y = std::accumulate(y.begin(), y.end(), 0.0);
const double s_xx = std::inner_product(x.begin(), x.end(), x.begin(), 0.0);
const double s_xy = std::inner_product(x.begin(), x.end(), y.begin(), 0.0);
const double numer = n * s_xy - s_x * s_y; // The same regardless of inversion (both terms here are commutative)
const double denom = n * s_xx - s_x * s_x; // Will change if inverted; use this for now
double a;
if (denom == 0) a = 2; // If slope is vertical, force variable inversion calculation
else a = numer / denom;
if (std::abs(a) > 1) { // Redo with variable inversion if slope is steeper than 1
const double s_yy = std::inner_product(y.begin(), y.end(), y.begin(), 0.0);
const double new_denom = n * s_yy - s_y * s_y;
a = new_denom / numer; // Invert the fraction because we've mirrored it around x=y
}
return a;
}
int main() {
std::vector<double> x{6, 5, 11, 7, 5, 4, 4};
std::vector<double> y{2, 3, 9, 1, 8, 7, 5};
std::cout << slope(x, y) << '\n';
}