近似デモ — 関数を多項式・有理式で近似する

sangi の近似モジュールは、データへの回帰から関数の一様近似、有理式近似まで統一的に扱える。 このページでは 3 つのデモで代表的なユースケースを紹介する。

Demo 1: 直線上のデータを線形回帰で復元する

$y=2x+1$ 上の 5 点を最小二乗線形回帰にかける。 データが厳密に直線上にあれば、傾き・切片は厳密に復元され、決定係数 $R^2=1$ になる。

=== Demo 1: Linear regression (data on y = 2x + 1) === slope = 2 intercept = 1 R^2 = 1
$R^2=1$ は回帰直線がデータを完全に説明することを意味する。実データでは $R^2<1$ になる。

Demo 2: Chebyshev 近似で exp を一様に近似する

区間 $[-1,1]$ 上で $e^x$ を 12 次の Chebyshev 近似で表す。 Chebyshev 級数は最良一様近似 (ミニマックス) にきわめて近く、区間全体でほぼ均等な誤差になる。

=== Demo 2: Chebyshev approximation of exp(x), degree 12 === cheb(-1) = 0.3678794412 exp(-1) = 0.3678794412 cheb(0) = 1 exp(0) = 1 cheb(1) = 2.718281828 exp(1) = 2.718281828
12 次でも誤差は $10^{-10}$ 程度に収まり、表示桁では真値と一致する。 Taylor 展開と違い区間端でも精度が落ちない。

Demo 3: Padé 近似は有理式で exp を近似する

$e^x$ の Taylor 係数から $[3/3]$ Padé 近似 $P_3(x)/Q_3(x)$ を構成する。 同じ次数の多項式より広い範囲で精度が高く、$x=2$ のように展開中心から離れた点でも破綻しにくい。

=== Demo 3: Pade [3/3] approximation of exp(x) === pade(1) = 2.718309859 exp(1) = 2.718281828 pade(2) = 7.4 exp(2) = 7.389056099
$[3/3]$ Padé は分子・分母とも 3 次。$x=1$ で 4 桁、$x=2$ でも 2 桁が一致し、 6 次 Taylor 多項式より広域で良い近似を与える。

ソースコードと実行方法

example_approximation.cpp (完全なソースコード)
// example_approximation.cpp — Approximation demo
#include <math/approx/approximation.hpp>
#include <iostream>
#include <iomanip>
#include <vector>
#include <span>
#include <cmath>
using namespace sangi;

int main() {
    std::cout << std::setprecision(10);

    // --- Demo 1: Linear regression of points on a line ---
    std::cout << "=== Demo 1: Linear regression (data on y = 2x + 1) ===\n";
    std::vector<double> x = {0.0, 1.0, 2.0, 3.0, 4.0};
    std::vector<double> y = {1.0, 3.0, 5.0, 7.0, 9.0};
    auto lr = linearRegression(x, y);
    std::cout << "  slope     = " << lr.slope << "\n";
    std::cout << "  intercept = " << lr.intercept << "\n";
    std::cout << "  R^2       = " << lr.r_squared << "\n";

    // --- Demo 2: Chebyshev approximation of exp on [-1, 1] ---
    std::cout << "\n=== Demo 2: Chebyshev approximation of exp(x), degree 12 ===\n";
    ChebyshevApprox<double> cheb([](double t) { return std::exp(t); }, -1.0, 1.0, 12);
    for (double xi : {-1.0, 0.0, 1.0})
        std::cout << "  cheb(" << xi << ") = " << cheb(xi)
                  << "   exp(" << xi << ") = " << std::exp(xi) << "\n";

    // --- Demo 3: Pade [3/3] approximation of exp ---
    std::cout << "\n=== Demo 3: Pade [3/3] approximation of exp(x) ===\n";
    std::vector<double> taylor = {
        1.0, 1.0, 1.0 / 2.0, 1.0 / 6.0, 1.0 / 24.0, 1.0 / 120.0, 1.0 / 720.0
    };
    auto pade = padeApprox(std::span<const double>(taylor), 3, 3);
    for (double xi : {1.0, 2.0})
        std::cout << "  pade(" << xi << ") = " << evaluatePade(pade, xi)
                  << "   exp(" << xi << ") = " << std::exp(xi) << "\n";

    return 0;
}

API の詳細は Approximation API リファレンス を参照のこと。

ビルドと実行

cd sangi
mkdir build && cd build
cmake .. -G "Visual Studio 17 2022" -A x64
cmake --build . --config Release --target example-approximation
examples\Release\example-approximation.exe