[151] F=(2*x^3+4*x^2+3)*(3*x^3+4*x^2+5)^10$ [152] G=(2*x^3+4*x^2+3)*(4*x^3+5*x^2+6)^30$ [153] H=g_c_d(F,G)$ 6.511sec + gc : 0.06728sec(6.647sec)使用する計算機にもよるが, 数秒程度で巨大な係数を持つ多項式が得られる. 実はこの多項式は
[154] ptozp(H); 2*x^3+4*x^2+3この例からわかるように, 前節の g_c_d では, 互除法の途中および 結果の多項式に分母分子が巨大な分数が現れてしまう. 人間と同様, 計算機 も分数の計算は苦手である. そこで, 分数の計算が現れないように工夫して みよう. まず, 剰余を定数倍しても, GCD は定数倍の影響を受けるだけという ことに注意して, 次のような関数を考える.
def remainder(F,G) { Q = 0; R = F; HCG = coef(G,deg(G,x)); while ((R != 0) && (deg(R,x) >= deg(G,x))) R = HCG*R-coef(R,deg(R,x))*x^(deg(R,x)-deg(G,x))*G; return R; }
この関数は, 適当な自然数 に対し
def g_c_d_1(F,G) { if (deg(F,x) > deg(G,x)) { S = F; T = G; }else { S = G; T = F; } while (T != 0) { R = pseudo_remainder(S,T); S = T; T = R; } return(S); }
[207] g_c_d_1(F,G); Needed to allocate blacklisted block at 0x988d000 Needed to allocate blacklisted block at 0x9899000どうしたことか, 妙なメッセージは出るものの結果は出そうもない. 実は, pseudo_remainder でかけた
def g_c_d_2(F,G) { if (deg(F,x) > deg(G,x)) { S = F; T = G; }else { S = G; T = F; } while (T != 0) { R = pseudo_remainder(S,T); R = ptozp(R); S = T; T = R; } return(S); }
[237] g_c_d_2(F,G); 2*x^3+4*x^2+3 0.057sec(0.06886sec)今度はずいぶん速く計算できた. ptozp では, 実際に係数の整数 GCD を計算することで 簡単化を行っているが, より詳しく調べると, GCD を計算しなくても, GCD のかなりの部分は あらかじめ知ることができる. この話題にはこれ以上立ち入らない. [3] Section 4.6.1 または [2] 5.4 節 を参照して欲しい.
ここで見たように, 互除法のような単純なアルゴリズムでも, 実現方法によっ てはずいぶん効率に差が出る場合がある. 特に, 分数が現れないようなアルゴ リズムを考えることは重要である.