5.Lucas列の計算方法


ynの値を直接計算する方法を考える。

ynについては、以下のような式が成り立つ。

(1) y2n=2ynyn+1−ayn2
(2) y2n+1=yn+12+byn2
(3) y2n+2=ayn+12+2bynyn+1

n番目と n+1番目から2n番目、2n+1番目、2n+2番目が生成されるということで、
以前、べき乗計算のときに使った、nを2進数に展開して、各桁のビットに応じて処理を行う、
という手法が使えそうである。


23を例に考えてみよう。
奇数番目を生成する式は、(2)しかない。

y23=y12+y11

つまり、12番目と11番目を計算しておく必要がある。

次に、11番目は奇数番目なので、生成する式は、(2)しかない。

y11=y6+y5

12番目をこの6番目と5番目から生成するには、(3)の式を使えばよい。

次に、5番目は奇数番目なので、生成する式は、(2)しかない。

y5=y3+y2

6番目をこの3番目と2番目から生成するには、(3)の式を使えばよい。

次に、3番目は奇数番目なので、生成する式は、(2)しかない。

y3=y2+y1

2番目は、0番目と1番目から生成されるが、(1)式より、2番目と1番目からも計算できる。


以上の流れをまとめると、以下のようになる。

w0:0→(2)→1→(1)→2→(2)→5→(2)→11→(2)→23
w1:1→(3)→2→(2)→3→(3)→6→(3)→12→(3)→24

23=(10111)2と、式の選択を見比べると、以下のアルゴリズムでn番目を求められることがわかる。

  1. nを2進展開する。y0=0、y1=1とする
  2. 最上位ビットから順に見ていき、
  3. w0が求める解

プログラムは以下のとおり。

 10   ' lucas sequence
 20   ' y(0)=0, y(1)=1, y(n+1)=ay(n)+by(n-1)
 30   fnYn1(N)
 40   local I,A,B,W0,W1,Y0,Y1
 50   dim W%(len(N))
 60   if N=0 then return(0)
 70   if N=1 then return(1)
 80   I=0
 90   while N>0
100     inc I:W%(I)=N@2:N=N\2
110   wend
120   W%(0)=I
130   '
140   A=1:B=1:Y0=0:Y1=1
150   for I=W%(0) to 1 step -1
160     if W%(I)=1 then W0=Y1^2+B*Y0^2:W1=A*Y1^2+2*B*Y0*Y1
170     if W%(I)=0 then W0=2*Y0*Y1-A*Y0^2:W1=Y1^2+B*Y0^2
180     Y0=W0:Y1=W1
190   next I
200   return(Y0)

0番目、1番目に対する例外処理は不要である。
また、UBASICでは、bit(i,n)により、nを2進展開したときの最下位からi番目のビットを取得できる。

これらを使って書き直すと以下のようになる。

 10   ' lucas sequence
 20   ' y(0)=0, y(1)=1, y(n+1)=ay(n)+by(n-1)
 30   fnYn2(N)
 40   local I,A,B,W0,W1,Y0,Y1
 50   dim W%(len(N))
 60   A=1:B=1:Y0=0:Y1=1
 70   for I=len(N)-1 to 0 step -1
 80     if bit(I,N)=1 then W0=Y1^2+B*Y0^2:W1=A*Y1^2+2*B*Y0*Y1
 90     if bit(I,N)=0 then W0=2*Y0*Y1-A*Y0^2:W1=Y1^2+B*Y0^2
100     Y0=W0:Y1=W1
110   next I
120   return(Y0)

この章の目次

E-mail : kc2h-msm@asahi-net.or.jp
三島 久典