ひとつ不良が出ている

ひとつ不良が出ている.n=7のとき1/nで固定部が1となっている.これは誤りだ.固定部:0でなくてはならない.10進数表記すると1/7=0.142857142857…で,循環節U=142857でnU = 142857*7 = 999999 = 9*111111となる.以下のURLによると,

An Efficient Factoring Algorithm by Repunit Number Method
http://www.aya.or.jp/~babalabo/repunit/index.html?fbclid=IwAR0HOaEACHvZ4MyWwXNk6_Dj4Tnr_BAJTjjLMKuBY3PyyhdLo61SbvqT3tY

[8′] Let p be a prime number which is neither 2 nor 5, and the recursion unit of p be U, then pU/9 is a repunit number Rn, i.e., pU=10n-1.

[8′] は証明されているので定理だが,これを拡張した [9] Let m be an integer without factor 2 nor 5, and the recursion unit of m be U, then mU/9 is a repunit number Rn, i.e., mU=10n-1.も定理である.

今のケースではn=7は素数であるから,これを満たさなくてはならない.今回はB進⇔10進の相互変換ができるようになっているので,それだけで十分だろうと思ってレピュニット関係のロジックはすべて削ってしまったのだが,ちょっと早まったかもしれない.ともかく,どこかが間違っていることは確かなので調べてみよう.循環節はTextBox5に書き込まれている.この文字列はConvertNum2Stringで生成しているが,文字列自体には誤りはない.maxfixedに入っている固定桁数が間違っている.というか,maxfixedをここで使っているのが間違っている.

少なくとも初期バージョンでは正しい値が出力されている.⇒正しく出力されるのはバックアップの中で一番古い「久留島喜内 2023-04-16」しかない.それから一つ上がると固定桁:3など間違った値が出始める.この版ではDispParametorの引数で渡されたfixed値をそのまま使っている.現行版ではMakeRecurringDecimalで渡されるfixedの値がすでに誤っている.InvertFuncが返している値が1になっている.fixed = IT(j)でIT()には,{6, 2, 1, 4, 5, 3}が入っている.IT(0)には値が設定されていない.どうも,InvertFuncの論理全体を見直す必要が出てきた.

InvertFuncで剰余が一致したときの操作が間違っている.初項に戻る場合はつねに剰余が1になっているという推定が誤りだ.RT(0)には初項の剰余が格納されているので,それと比較する必要がある.これで多分問題は解決したのではないかと思う.repunitに関する検査を追加しておこう.どこに入れればよいか?レピュニットが関係してくるのは逆数検定に限られている.Prime TestにはDivideRepunitが残っている.

SeedTestを実行して,ValueChanged文字列 str3とstr4の不一致で停止した.10新表記の場合は両者が一致する必要がある.確かに小数第12位で不一致が発生している.

“0.0714285714285714″
“0.071428071428071428071428071428071428″

N=14, B=10で起きている.714285の方が正しい.つまり,str3は間違っている.MakeRecurringDecimalで生成するstr2にも欠陥がある.これしか入っていない.”/A:0.&071428/”.str3を生成しているのはMakeDecimalStringだ.この関数はQT配列から文字列を生成している.QTに入っている値は正しい.引数でfixedとketaを渡しているが,fixedに0が入っている.これは1でなくてはならない.上の修正で初項に一致した場合には強制的に1を代入しているが,これがまずいのだろう.

固定項には0の並びが含まれる場合がある.それをどうやって判定したらよいのだろう?QT(0)=0の場合はfixed=1となるようにして逃げた.とりあえずこれで動作するようになったが,これですべてカバーできるようになっているかどうかは疑問だ.どうもうまく行っていないようだ.n=6, B=10のとき,str3=0.11111111111111… のようになってしまう.R=4でIT(j)=1かつR=RT(0)が成立し,QT(0) が0でないのでfixed=0に設定している.1/6=0.16666…なので,固定部は1でなくてはならないのだが,誤動作している.

どうも,InvertFuncのアルゴリズムは仕上がっていないのではないだろうか?InvertFuncではQT, RT, ITの3つの配列を使っている.ここではB^i mod N を計算し,剰余が一致すれば周期が閉じたと判定して,固定部長と周期を割り出すことになっている.ループからの脱出条件は,①剰余がゼロになった,②一致する剰余を検出,③中止ボタンないしカウントオーバーの3つだ.問題が起きているのは,②の周期の終端に達して剰余が一致したという場合だ.ResidueFuncではドロップ項というのを見ているが,その操作が欠けているのではないだろうか?つまり,剰余が一致したというだけでは不十分なのではないか?

それを確認するためには,QTを見て,同一Qの発生時点まで進む必要があるように思われる.⇒できたようだ.ポイントは2つ.①QT(0)=0つまり,商が立たない場合には商が立つところまで進む必要があること,②異なる商が立っていた場合には,商が一致するところまで進む必要があること.これで,ドロップ項を見なくても固定部を正しく同定することができるようになった.この論理は剰余数列の方にも使えるのではないだろうか?もし,それが可能ならロスタイムを少しでも減少される効果はあるかもしれない.ともかく,一度バックアップを取っておこう.

N=14,B=16のとき,PrimeTestで停止した.fixed > 0 And i <> fixed + ketaが起きている.10進なら1/14=0.07142857142857…だが,16進なのでどういうことになるのか… i=4でfixed=6, keta=6になっている.fixedの6というのは明らかに誤りと思われる.多分,これは正しいのではないかと思う.str3=0.12492492492492492 だとすれば,固定部1,循環部3ということになる.1+3=4=iで計算も合う.

QT(0)=1で最初から商は立っている.Qは9なので,上からQTを探して,QT(3)=9を検出し,fixed=3としている.どこが間違っているのか?⇒QT(0)が非ゼロのとき,Qを探しに行ってオーバーランしている.i の範囲を超えたときには,fixed=1としなくてはならない.なぜなら,IT(j) = 1 And R = RT(0)であるから,初項から循環に入ることは間違いではないが,循環が完成するためにはRだけでなく,Qも一致する必要があるが,周期が短いときには,初項で発生するQがまだどこにも出現していない場合がある.そのような場合でも,初項のRが一致していることは初項の次の項から循環が始まることを意味しているからだ.

これでまず,穴は全部塞げたのではないかと思う.検算を兼ねてレピュニット関係の検定を導入しておくことは意味があると思う.まず最初に冒頭に出てきたnUというのを作ってみよう.nと除数pが互いに素の場合には循環周期Uをn倍したもの/p-1がレピュニット数になるというものだ.つまり,nのbベースの循環節をUとするとき,nとbが互いに素であれば,nU=n^(b-1)/(b-1).実装されているレピュニット関係の関数を集めておこう.まず,現行バージョンには以下がある.

  1. DivideRepunit ∑B^i mod n ある桁数のレピュニット数のnを法とする剰余
  2. RepuitFunc ∑B^i ある桁数のレピュニット数を求める

オリジナルソースを見てみたが,これですべてだ.つまり,大したことはやっていない.DivideRepunit はレピュニット数が桁数で割り切れるかどうかを見ているだけだ.これはちょっと後回しにして,InvertFuncとResidueFuncで同じ論理が使えるかどうかを見ておくことにしよう.まず,InvertFuncから主要ロジックを切り出してみよう.この処理の主眼は,nとbを指定して固定桁と循環部の長さを決定することだ.

N=7, B=2のとき,PowerResidueFuncで i <> fixed + keta のエラーになった.i=4 <> fixed=2+keta=3=5.N=7は2進表記では111だが,1/7は0.00100100100…のようになるので,fixed=2, keta=3が正しいように思われる.⇒ fixed ≠ IT(j) となる場合はあり得る.今の場合がそうだ.QT(0)=0の後に0が続く場合はそのようなことが起こる.⇒このような場合には(フラグを立てて)パスするようにした.

▲n=7, B=1のとき,ValueChangedで停止した.If QT(i) > Bというエラーだ.keta=0でfixed=6だ.B=1の場合はQT()は1の並びにならなくてはならないはずなのだが… ⇒従来論理ではEXITINVERTFUNCでQTの補充というのをやっているが,暫定的に止めてある.また,B=1, N=1の場合にはPowerResidueFuncを通さないでストレートにEXITINVERTFUNCに飛ぶようになっているので,QTが前の状態のまま残留しているのだろう.⇒どうも,これはかなり難しい問題だ.

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA