ユークリッドの互除法 (Euclidean Algorithm) は最大公約数 (GCD) を求めるときに使うアルゴリズムとして有名ですが、連分数 (continued fraction) 展開にも適用できます。
[ 戻る ]
| n | 部分商 an | 近似分数 pn/qn |
|---|
[ 戻る ]
[ 戻る ]
[ 戻る ]
2つの自然数a, b(≠0)について、aをbで除したときの商 (quotient) をq、剰余 (remainder) をr としたとき、qが連分数の部分商 (項) となります。
右側の式の を新たに とおいて、r=0 となるまで計算を繰り返すことで、全ての部分商を得ることができます。
var euclidean = function(a, b) {
/* Euclidean Algorithmによる連分数展開 */
var q = [], r;
var i = 0;
const max_term = 100; // 最大項数
while (b !== 0 && i <= max_term) {
q[i++] = Math.floor(a / b);
r = a % b;
a = b;
b = r;
}
return q;
};
eucldiean(a,b)関数の第1引数 a は連分数展開する数値の分子、第2引数 b は分母で、戻り値は連分数の部分商配列です。
最大公約数の計算では停止性 (termination) が保証されていますが、実数の連分数展開では、丸め誤差 (rounding error) の蓄積や桁落ち (cancellation) による有功桁数 (significant digits) の減少により、停止性が確実に保証されているとは言い切れません。このため、最大項数 max_term によって停止性を保証しています。
アルゴリズム上では a≥b の必要がありますが、a<b であっても1周目のループで aとbが交換され、条件を満たすようになります。
部分商 a[n] から近似分数 pn/qn を以下の漸化式で求めることができます。
若しくは上の漸化式を行列化して求めることもできます。当研究室ではこちらを採用しています。
/* 連分数展開による近似分数 */
var multi_matrix = function(a, b) {
/* 2×2行列の積 */
return [[a[0][0] * b[0][0] + a[0][1] * b[1][0], a[0][0] * b[0][1] + a[0][1] * b[1][1]],
[a[1][0] * b[0][0] + a[1][1] * b[1][0], a[1][0] * b[0][1] + a[1][1] * b[1][1]]];
};
var a = euclidean(num, denom); // num/denomの連分数展開
var convergent = [[1, 0], [0, 1]]; // 連分数展開における近似分数(convergent)
var conv_text = []; // 近似分数の文字列配列
for (var i = 0; i < a.length; i++) {
convergent = multi_matrix(convergent, [[a[i], 1], [1, 0]]);
conv_text[i] = convergent[0][0] + '/' + convergent[1][0];
}
表の可変行数に関するアルゴリズムは、小技集 "Tips!" で公開しています。
[ 戻る ]
[ 戻る ]