近似デモ — 関数を多項式・有理式で近似する
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