808 words
4 minutes
数値計算アルゴリズム
ユークリッドの互除法(Euclidean Algorithm)
ユークリッドの互除法は,2つの自然数の最大公約数を求めるための古典的なアルゴリズムである.とした場合,の関係を用いて下記コードのように求めることができる.
int _gcd(int a, int b){ return b == 0 ? a : _gcd(b, a % b);}
を考慮した実装(の大小比較)は[gcd.cpp]を参照されたい.
最小公倍数(Least common multiple)
正整数に対して,最大公約数と最小公倍数の間には,
の関係があるので,下記コードにて求めることができる.完全なコードは,[lcm.cpp]を参照されたい.
int lcm(int a, int b){ return a * b / gcd(a, b);}
ニュートン法(Newton’s method)
ニュートン法は数値計算による方程式解法で,微分可能性と2次微分符号を条件に,反復法で求根を行う.問題を定式化すると,関数として,となるを求めること限定する.このとき,の付近に適当な値をとり,次の漸化式によって,に収束する数列を得ることができる場合が多い.
具体的には,以下の反復を行う.完全なコードは,[newton.cpp]を参照されたい.
double x0 = 1.0;double tolerance = 1e-6;int max_iter = 1000;int iter = 0;
while (iter < max_iter){ double x1 = x0 - f(x0) / df(x0);
if (abs(x1 - x0) < tolerance) break;
x0 = x1; iter++;}
ガウスの消去法(Gaussian elimination)
ガウスの消去法は,線形方程式系 を解くために係数行列 を前進消去(forward elimination)と後退代入(back substitution)によって上三角行列へ変換し,逐次的に解を求める直接法である.前進消去では,行基本変形により,対角成分を基準に下側の成分をゼロにする.数値的安定性を考慮する場合,部分ピボット選択(partial pivoting)を併用する.後退代入により,最下行から順に未知数を逐次決定し,最終的に解ベクトル を得る.完全なコードは,[gauss.cpp]を参照されたい.
vector<double> gauss(vector<vector<double>> A, vector<double> b){ int n = A.size(); for (int i = 0; i < n; i++) { int p = i; for (int j = i + 1; j < n; j++) if (abs(A[j][i]) > abs(A[p][i])) p = j; swap(A[i], A[p]), swap(b[i], b[p]); for (int j = i + 1; j < n; j++) { double f = A[j][i] / A[i][i]; for (int k = i; k < n; k++) A[j][k] -= f * A[i][k]; b[j] -= f * b[i]; } } vector<double> x(n); for (int i = n - 1; i >= 0; i--) { x[i] = b[i]; for (int j = i + 1; j < n; j++) x[i] -= A[i][j] * x[j]; x[i] /= A[i][i]; } return x;}
素数判定(Primality test)
素数判定とは,与えられた自然数が素数か合成数かを判定することである.素数判定を行うアルゴリズムを素数判定法という.完全なコードは,[check_prime.cpp]を参照されたい.
bool is_prime(unsigned int n){ if (n < 2) return false; if (n == 2) return true; if (n % 2 == 0) return false; for (unsigned int i = 3; i * i <= n; i += 2) { if (n % i == 0) return false; } return true;}
Waiting for api.github.com...