B進小数表記に関してはほぼ完全になったのではないか

かなり進んだ.B進小数表記に関してはほぼ完全になったのではないかと思う.というか,チェックしたのは10進法だけなので,B進表記のすべての動作を確認した訳ではないが,主要な論理は通っているはずだ.昨日は障害が発生したところで止まっている.続きをやることにしよう.

1234567891という数字を与えて,InvertFuncで停止する.RT(rindex) <> 0が起きている.⇒初期値としてこの数を設定して起動→どこかでハングしてしまっている.⇒どうも,Enumerable.Repeat(Of BigInteger)(0, arraysize).ToArray()で手間取っているようだ.arraysize=536608768.この数字はMAXARRAYSIZEですでに限界に達していることを示している.IT(arraysize)を生成するのにもかなり掛かっているようだ.RTとITも固定で外に出してしまった方がよいのではないだろうか?使うときには必ず初期化が必要になるので,大したメリットはないかもしれないが…

ウォッチパネルでこれらの配列の中を見ようとするとそれだけでハングしてしまうので,開けることもできない.問題が起きているのは,rindex={454561898}なので,ここだけ見ることはできるだろう.このときのRは{991170666}だ.IT(454561898)には2415という値が入っている.しかし,不審なのはRTにrindexの値が入っているという点だ.rindexを設定している箇所はこの関数の中で7箇所もある.これはかなり間違え易い論理だ.R=454561898でrindex=454561898となっている.このときは,まだRTには書き込まれていない.従って,ここに書き込むまではノーマルな動作だ.⇒すでに書き込まれていたときの空セル検出の論理が間違っている.

RTはハッシュテーブルなので,テーブルの末端まで検索しなくてはならないのにデータカウントまでで打ち切っていた.どうも10進10桁というのは,このツールの限界のように思われる.循環節の長さが十分短ければもっと小さいテーブルでもよいのだが,一般に大きい数では周期も長くなることが多いので,あまり小さくすることはできない.対象数の約数と循環節の周期には相関があるだろうか?もし,それがわかればある程度調整できるのではないか?BとNが互いに素の場合が最長になるのではないかという気がするのだが…

1234567891は素数だった.3は素数だが,循環桁数は1なので,Nが素数であるか否かと循環桁は直接結びつかないが,数字が大きくなると循環桁が伸びる傾向にあるのは確かだ.相当時間が経過しているが,まだ10%程度しかこなしていない.これ以上続けても埒が明かないので,一度中断しておこう.配列の初期化には相当の時間が掛かるので,上書き可能な配列は初期化しないことにする.RTはハッシュテーブルなので初期化する以外ないが,ITとQTは初期化しなくても動作するはずだ.

画面を処理に先行して表示するために,ValueChangedの実行をMyBase.Shownイベントが発生するまで抑制するようにした.これで,画面が開かれたときには,すでに因数分解も完了し,φなどのパラメータも表示された状態になっている.その数が素数であることも明示したい.⇒「P」というラベルのボタン型チェックボックスを新設した.

ビジー状態だと,カーソルが飛んでしまうため,STOPボタンを押すことができない.ESCキーを受け付けるようにしておこう.⇒実装した.Stopは効くようになったが(効きはあまりよくない),停止しない.⇒MyBase.Shownイベントが反復掛かってきているようだ.⇒フラグを見るようにして,一応解決.

なぜか理由はよく分からないが,RTはInvertFuncのローカル変数としておいた方が速い.ITは内部に置くとかなり時間が掛かってしまうのだが… メモリを大量消費した後のガベージコレクションのような作業で手間取っているような感じ.とりあえず,これが最速なのでこれでフィックスということにしておきたい.

N=12でエラー終了になった.stopflagをリセットしていなかったためではないか?⇒対処した.

ESCキーの効きは悪いが,なぜかStopボタンが押せるようになった.ただし,あまり効きのよいものではない.何度も繰り返し押すうちに入るという感じだ.Stopで停止した後もまだ,しばらく制御が戻ってこない.なぜだろう?走行中にブレークポイントを設定できないくらいなのだから,よほどビジーなのだろう.まぁ,これはこれ以上どうしようもない… タスクバーのアイコンを点滅させるという仕組みは完全に廃止.

加納氏の出題に応答するために,べき剰余検定の機能を少し変更することにしよう.現行ではボタンが3つあり,「n^p%k」「p=1→k」「n=min→max Test」となっているが,「p=1→k」のところを,「n^p^m m=1→k %k」とすることにする.「p=1→k」と同等動作にするためには,p=1で実行すればよいというだけだから,十分な拡張になっている.「n^p^m m=1→k %k」の動作は,まず,n^p%k=αを計算したのち,α^p%kを実行するようになるものと思われる.ただし,これだけではたとえば,

2021^2022^2023

のような計算をストレートに実行することはできないが,いまのところは,これが限界だ.しかし,2021^2023%100=41のとき,41^2023%100=21になってしまうのはなぜだろう?これでは話が合わないような気がするのだが…この辺り,動作を確認しながら少しチェックする必要がある.とりあえず,ここで一度バックアップ.

計算は完全に(wolframと)合っている.計算完了後制御が戻るまでにしばらく掛かるという現象がある.いや,今度はすぐ戻ってきた.41^2023%100という計算なのだが…再現しなくなってしまった.⇒原因は分かった.テキストボックスに入力すると即時応答しようとしているためだ.これは不要な機能だろう.いや,おかしい.TextBox1ではTextChangedを取っていない.

どうも,動作がおかしい.Button2.Clickイベントが入っているようだ.⇒ボタン名を変えておこう.modulo1, modulo2, modulo3としておく.どうも,かなり様子がおかしい.押してもいないのに,SeedTestボタンが入っている.Clearボタンも青くなっている.

One Shotを3回繰り返すと,ハング状態になる.このとき,

‘Kinai.exe’ (CoreCLR: clrhost): ‘C:\Program Files\dotnet\shared\Microsoft.NETCore.App\5.0.17\System.Runtime.CompilerServices.Unsafe.dll’ が読み込まれました。

などのDLLが追加で読み込まれてくるのだが…どうも,これを読み込む間コントロール喪失状態になっているようだ.上記のSeedTestボタンはClearボタンを押すつもりで押し間違えた可能性がある.どうも,まだやはり具合の悪いところがある.今度は別のDLLガロードされてきた.

‘Kinai.exe’ (CoreCLR: clrhost): ‘C:\Program Files\dotnet\shared\Microsoft.NETCore.App\5.0.17\System.Collections.Concurrent.dll’ が読み込まれました。

DLLのロード中はコントロールが効かない.ロードし終わると問題なく動作するようになる.リリース版をビルドしてみよう.やはり,同じ現象が起こる.復旧するまでの時間はかなり長い.イベントループが回らなくなっているというか,詰まっている感じ.ボタン処理を実行している間,砂時計を出すようにした.Periodicでは出力画面に書き込みしたあともまだ何かやっているようだ.

BigInteger.Pow→.Mod をModPowでまとめてやるようにして,何とか収まったようだ.modulo1は現行のままとし,べき乗の結果の大きな値を画面出力できるようにしておこう.

2021のSeedTestで停止した.「WRONG SAMPLE」fixed=0かつk=0つまり桁数ゼロという状態になっている.このテストはN=1~nをテストするもので,n=1, b=10で始まっている.1/1=1.0で固定桁数というのは小数部しか含まないので,この場合は,fixed=0, k=0となるのは仕方ない.つまり,不良ではない.

Daily Epsilon of Mathで手一杯

どうも,FBのDaily Epsilon of Mathのカバーで手一杯になっている.日めくりカレンダーなので,提出した課題は翌日には解かなくてはならない.誰かが回答ないしヒントを寄せてくれた場合はよいが,昨日の設問にはまったくコメントが付かなかった.かといって,それで放置という訳にもゆかない.そうなるとあとは自力で何とか解くしかないのだが,わたしからすると絶壁を直攀するような難事だ.昨日の分に関してはネットを探しまくってなんとか回答をまとめた.かなり厳しい.今日もまだ少し仕事が残っている.回答に補足を付ける作業だ.それをやっておかないと,あとで同じような問題に出くわしたとき,また一から同じことを繰り返さなくてはならない.⇒片付いた.今日の課題は暗算問題だから,回答を付けるものも簡単だ.ようやく仕事に戻れる.

大体まとまってきているはずなのだが,いま躓いているのは,3という小さな数だ.⇒3は正しく処理されているが,6で間違えている.fixed=0, k=1で/A:0.&1/としている.これは/A:0.1&6/でなくてはならない.j=4, IT(j)=0となっている.i=2だ.しかし,ITに0が入っていること自体おかしいような気がする.いや,違うR = RT(0)という理由でfixed = IT(j) – 1としているためだ.どうも,まだ読み損なっているような気がする.いまの場合,計算は10\6を計算するところから始まる.R=4はRT(0)とRT(rindex=4)に格納されている.⇒ようやく収まったのではないか?判定のところでR=1を見るようにして切り分けできるようになった.3や9の場合にはR=1で脱出するようになっている.これは初期状態ですでに周期に入っているということを意味するからだ.

出力が整合しているかどうかを確認する方法を考える必要がある.現行のInvertFuncのように整数化して検査すれば確実なことが分かるが,ここで浪費する時間コストを削減するために修正しようとしているのだから,もっと軽い処理でなくてはならない.倍精度で出力し,小数点以下の数字を拾い出すというのではどうか?それほど数が大きくならない限り,正確な検査ができるはずだ.倍精度をテキスト出力してそれと直接比較すればよいのではないか?比較する桁数は固定部+循環部とすればよい.ということになるとすると,MakeRecurringDecimalでもう一種類の出力を作り出さなくてはならない.つまり,普通の小数だ.それもよいのではないか?倍精度の有効桁数までの文字列を生成するというのは悪い発想ではない.double.ToString(“Exx”)で出力桁数を指定できる.しかし,これでは前方の0の部分が分からない.”Gxx”で有効桁数を指定できるが,これではやや指定があいまいだ.”Nxx”という指定が分かり易いのではないか?これは小数部の桁数を指定するものだが,指数表示部がないので,正確なポジションが分かる.

doubleの有効桁数はこんなに少なかったのだろうか?1/3を小数24位まで出力させたら,こんな数字が出てきた.

0.333333333333333314829616

16桁しかない.確かに単精度で7桁,倍精度で15桁というのが上限のようだ.decimalという整数型なら28桁まで格納できる.しかし,もちろん小数は扱えない.とりあえず,16桁まで検査できればチェックにはなるだろう.⇒いや,どうもあまり大した検査にはならないような気がする.1234567という7桁の数値を小数化したとき,固定桁が1,循環桁が68041が正しいかどうか知りたいのだが,16桁では話にならない.固定桁は”0”一桁ということになっているのだが,これを知るためには,少なくとも68041桁の次に続く数字を見なくてはならない.現在4種類の数字列を出力しているが,すでに正規化されているため,循環節の続きは出力されていない.

いや,DispInvertでは2*k桁まで見ているはずだ.ValueChangedの中でQTの内容をダンプしているが,fixed+kで打ち切っている.これをもう少し伸ばせばよい.⇒いや,QTテーブル自体打ち切りになっているようだ.中身がゼロの並びになってしまっている.いや,実際循環部の終端を検出するとInvertFuncのループから離脱するようになっているのだから,当然のことだ.これはもはや,現在の論理を信頼するしかないのではないか?QTというテーブルはQ = BigInteger.DivRem(x, n, R)を格納しているというだけだから,出口でもう少しテーブルを増長させるということは可能なのではないか?一度終了してバックアップを取ってから着手することにしよう.InvertFuncの出口を一箇所に絞りたいのだが… 一番簡単なgoto文で飛ばしてしまえばよいのではないか?

n=2でどこかでハングしてしまう.⇒MakeDecimalStringでおまけを付けているところで,k=0であるため,ループから抜けられなくなっている.⇒今度は例外が発生した.MakeDecimalStringで後ろにゼロを付け足していないためではないか?

対処完了した.完全に接続した.wolfram は循環節の長さを出せるので,比較チェックしてみよう.123456:107桁,1234567:34020桁,12345678:335616桁,123456789:6855006桁.さすがのwolframもここまでは届かなかったようだ.標準の計算時間制限を超えました…で打ち切りになってしまう.ただし,おそらく有料版なら出力できるのだろう.桁数を計算するまでは十分高速なのだが,数字列を組み立てるところでは相当な時間を消費してしまう.これはどっちみちダンプできる分量ではないので,どこかで打ち切るようにした方がよい.

まず,テキストボックスに格納できるバイト数というのが一つの目安ではないだろうか?現行ではテキストボックスは32767が上限となっているので,ここで打ち切ることにする.⇒少し削り過ぎてしまったのだろうか?Inverseのボックスが空のままだ.TextBox5だ.DispInvertを丸ごと止めているからだ.ここで書き込んでいたはずだ.inverseは入るようになったが,桁数が更新されない.これらの値は,DispParametorで出力するのが適当だろう.

123456789と1234567890の桁数が同じ数字6855006になっているが,大丈夫だろうか?6855006は内部的な上限なのではないだろうか?MAXARRAYSIZE=536608768だから,それよりもだいぶ小さい.PSIで時間を消費しているが,PHIのあと,MakeDecimalStringに入るまでのところでも時間が掛かっている.確かに,arraysizeがMAXARRAYSIZEになっている.QTのRedimを行わないようにしたら簡単に抜けてきた.やはりPSIがネックになっている.

1234567890を最後まで計算して抜けてきたが,やはり循環節の長さは同じだ.いや,これはこれでよいのだろう?後ろに0を1個追加しただけなのだから,周期が変わらないのは当然かもしれない.

▲12345678791を入力して,InvertFuncで停止した.RT(rindex) <> 0が発生している.rindex={454561898}でかなり大きな数字だ.RT(rindex) にはrindexと同じ数が入っている.かなり

InvertFuncで直接循環周期列を生成

InvertFuncの中で直接循環周期列を生成するという方式変更がまだ収束していない.⇒ようやく整理が付いたが,まだ不具合がある.2は通ったが,3で不一致が生じている.1/3=0.3333…だから,固定桁0, 循環桁1でなくてはならないのに,固定1,循環1になっている.⇒調整した.今度は4で0.2という値が出てきた.x=1から始めているので,10÷4=2になってしまう.勘違いしていた.1/4=0.25が正解だ.旧版で0.25は出ているが,訂版でQが足りない.0.20となっている.Qを格納する前に離脱しているためだ.QTはQが確定した時点で書き込みできるので,先行して格納してやればよい.

1/10で停止した.ただし,今回は訂版の方が正しい,旧版が0.0に対し,新版は0.1と正しい答えを返している.旧版にも穴があったということだろうか?7桁になるとさすがに重くなる.点滅も出ない.⇒8桁の12345678までの動作は確認した.旧版でn=10, b=10のとき,誤動作が起きる件に関しては別途しらべておく必要がある.この論理は最終的に破棄されることになるので,やらなくても構わないのだが,一応その原因は突き止めておいた方がよい.

いや,まだ12345678の処理は完了していない.ToBCDの引数のvalが配列サイズ上限の536608768を超えてしまっている.処理ではオーバーフローした分は切り捨てるようになっているようだが,最後まで実行できるだろうか?この小数は固定桁1,循環桁335616なので,改訂版なら問題なく処理できる範囲だが…⇒まだまだ掛かりそうなので一端打ち切ることにしよう.n=10, b=10の場合,ConvertNum2Stringをnn=1, b=10で呼び出して,nnstrに値が入ってこない.

ConvertNum2Stringから呼び出しているToBCDでは,val≦1では無動作で抜けている.ToBCDではvalをbで割る計算をしているので,n=1ないし,b=1では停止しないためではないか?いや,ここではこれらの値を除外する理由はないように思われる.いや,少なくともb=1ではこの論理では無限ループになってしまう.⇒b=1では抜けるようにした.これで正しく動作するようになった.

n=1, b=2でInvertを実行したら,inverseの値が消えたままになる.リターンキーで更新を実行しても埋まらない.なぜだろう?この値はTextBox5として表示されている.DispInvertでは暫定措置として,n=1の場合はTextBox5を空として離脱している.これは,n=1の場合のテキストが無闇に長くなることを回避するための措置と考えられるが,nnstr = “/” + basestr + “:1.0&/”をそのまま表示でよいのではないか?⇒大体これで収まったのではないか?いや,まだ数値が合っていない.

両方間違っている.n=123ではn=123 b=10 fixed=1 k=5 keta=6としているが,実際はfixed=0 k=6でなくてはならない.実際1/123=0.00813008130081300813008130081301で循環部は,0081300813だ.InvertFuncにまだ不良が残っている.⇒fixed = IT(j) – 1のように調整してみたが,却って悪い.たとえば,n=12の場合,1/12=0.083333だが,固定桁1, 循環1で/A:0.0&8/のようになってしまう.RT(0)を格納して,i=1の場合はfixed=0となるように調整した.

n=10, b=10の場合,fixed=0, k=0になってしまう.1/10=0.1だから,固定1でなくてはならないのだが… ダメだ.まだ合わない.n=6, b=10でfixed=0 K=1になってしまう.1/6=0.1666 でfixed=1,k=1でなくてはならない.InvertFuncの論理では,Q=x*b\n…Rを計算している.初回は1*10\6=1でR=4となる.次回は4*10\6で6…4.ここでR(0)=10%6=4なので,fx=0,k=1となってしまう.

大体合うようになったが,3の場合,fx=1, k=1 になってしまう.1/3=0.333なのでfx=0, k=1でなくてはならない.結局,3と6の切り分けがつかない状態になっている.

InvertFuncの中で直接循環周期列を生成するという方式変更

InvertFuncの中で直接循環周期列を生成するという方式変更をインプリメントしているところだが,どうも,かなり問題がありそうだ.既存コードと出力が一致しない.後ろの方が切れてしまっている.従来論理では周期列の2倍の長さのサンプルを用意してそこから切り出すようにしているが,改訂版では周期が判明した時点で処理を打ち切っているというところがまずいのだろうか?もし,そうであるとしたら,どこを修正すればよいのだろう?InvertFuncではQT()という配列に商を格納して返しているのだが,おそらく,冒頭でx≧nになるまで空回ししているところに問題があると思われるのだが,そこの論理は従来と同じなので,まず,従来論理との不一致が発生する理由から突き止める必要がある.

サンプル=1234で10進数のとき,末尾の5008103727が不足している.10桁だ.従来論理にはzerosupという処理が入っいるが,結果として出力されている数列では冒頭部分はまったく同一だ.改訂版にはこの措置は入っていないのに同一文字列になるというのもよくわからない.⇒従来論理では1/nをbのべき乗倍して整数化しているが,数値をnで割っても頭の方では商が立たないため,それを補うためのゼロ補正と考えられる.QTの中には冒頭のゼロも入っているため,同一結果になると考えられる.論理的にはこれでよいのではないだろうか?従って,問題は末尾に並ぶゼロの列ということになる.

やはり,問題はfixedではないだろうか?rcount=kであるということは,fixedの分は配列に格納されていないということになる.いや,rcountは上がっている.むしろ空回しのとき,fixedが上がってない方が問題なのではないだろうか?fixedはR=0のとき,x>=nの場合に限りインクリメントされている.いや,ちょっと違うかな?fixedの値は出口で決めているので,インクリメント操作は受けていない.k=i – IT(rindex)という値を返している.keta=fixed+kで,ketaが配列サイズに等しくなることを期待しているのだが…配列サイズはrcountだが,現在はこのテーブルはハッシュテーブルとして使っているので,必ずしも前詰めされていない.

InvertFuncは最近ハッシュ値を使うように仕様変更しているが,この修正に抜けがあるのではないか?rindexから後方しか探していないが,これでは全数検索したことにならないのでは?この修正は2023/04/17に入れているが,4月16日のコードと比較してみよう.いや,その下のループでそれはやっているようだ.同じコードがダブってしまうが,実害はないと思われるので修正を入れた.あとで整理することにする.

出力文字列が正しいことを検算する方法を考えなくてはならない.InvertFuncを用いずに直接検査することは可能だろうか?方法はあるだろう.文字列から整数を生成してしまうのが速いのではないか?いや,そんな簡単な話ではない.循環列は無限に反復する無限級数になっているので,そのΣを取らなくては元の数字にはならない.InvertFuncの動作(の模倣)ならあるいは可能かもしれない.つまり,nを頭から割り込んで剰余が一致するところが検出できたときの下図が一致すればよいのではないか?⇒検算は必要だが,ここでは保留しておこう.

テキストの長さと桁数では7の差がある.この7という数字は文字列に詰め込まれた記号で/B:0.&/の7文字だ.従って,桁数と配列長は一致している.問題はn=1234で10進数の場合,末尾の5008103727の10桁が欠損しているというところだ.これは結局,QTに書き漏らしがあることを意味する.MakeRecurringDecimalよりも前の問題だ.1から始めよう.現行論理では1は例外として扱うしかない.

φ,ψなどがすべて1になっている.これで正しいか?ここは後でチェックすることにして,2を見てみよう.従来論理では正しく0.5を表示しているが,改訂版では0.0で5が入ってこない.なぜか?xの初期値は1だが,x=x*bから始めるので,i=1でx=10,これを2で割って商が5というのはよいが,fixed=i=1で固定部が立ってしまう.

Open Live Writer の動作がおかしい

Open Live Writer の動作がおかしい.タスクバーのアイコンからオープンしたが,すぐ画面から消えてしまったので,一度閉じて再度開いたところ,随分前のドラフトを開いてきた.

image

このファイルはすでに公開されているし保存もしてあるのだが,これまでにも「修復しますか?」というメッセージが何度も出てその都度処理しているのに,時折思い出したようにゴーストとなって立ち上がって来る.その後,以下のような真っ赤なパネルがポップアップしてきた.

image

このパネルは,前にも少なくとも一度は見たことがある.以下のようなエラーも表示された.

image

エラーレポートには大したことは記載されていなかった.起動時にファイルが画面から消えたというのは,多分,モニターを切り替えたためと思われる.赤いパネルは何かのメッセージと思われるが,意味不明だ.

ともかく,先に進もう.大きい数字を扱えるようにするために可能なことをあれこれやっているが,その一環として,プログレスバーを廃止し,その代わりにタスクバー上のアイコンを点滅させることにした.この動作は一般にアプリをインストールする操作中にパネルが他のウィンドウの影に隠れてしまった場合,ユーザに注意を促すために使われるものなので,用法としてはやや変則だが,点滅が止まれば処理は完了しているというメッセージと解釈できるので,長く掛かりそうな場合には,放置して他のことをやるなどの応対が考えられるので,それなりに有効なのではないかと思う.

もう一つの対策として,現在valueの入力ボックスでテキストが更新された場合にはパラメータ表示を即時更新するようにしているのを,リターンキーが入力されたときにのみ確定入力として処理するよう仕様変更することにした.あちこち仕掛りになっているのだが,使い勝手にも影響するところなので,まずこれを先付けで修正を入れることにする.

キーイベントが入ってこない.なぜだろう?どこかのコントロールにフォーカスがあると,そのコントロールにイベントがパスされて,そこで明示的に放棄しないと回ってこないのではなかったろうか?ZELKOVAでは一覧画面でなにかその辺りを対策していたような気がするのだが… ⇒KeyPreviewというプロパティをオンにすればよい.⇒動作するようになった.Enterキーを受け付けたときは,長い処理でも打ち切らないようにしておこう.(自発的に指示しているので待つことができる)

おかしい,1234567の7桁で配列サイズオーバーが発生した.ToBCDで起きている.ToBCDが使っている配列はInt16.MaxValueの固定サイズだ.循環周期は34020>32767=Int16.MaxValueで明らかにオーバーしている.循環数列は計算に使っているのではなく,単に表示しているだけなのだから,打ち切ってもよいのではないか?実際,小さいテキストボックスに30000文字を格納するというのは現実的ではない.

テキストボックスのサイズは32767になっているから,その範囲なら格納することは可能だ.bcdNumberにはこの制限はかかっていないが,この値は最終的にnotation.Textに格納されるので,それ以上長い文字列を作っても意味がない.現在MAXARRAYSIZEには,536,608,768という数字が入っている.これはInt16.MaxValueよりはずっと大きいので,ここまではとりあえず処理してもよいのではないか?配列サイズをMAXARRAYSIZE固定としてとりあえず,動作した.1/1234567の固定部は73桁,循環部は34020桁で,冒頭は

A:0.000000810000591300431649315104000025920018921613812778083328000829
4406054&91642008898666496026542099375732544284757327872849347180023441
41711223449193117910976075012534759150374179773151234400401112292811973
75274083950081283559336998316008770686402601073898783946112280661964883

のような巨大テキストだ.value=1234567890として10桁入力してENTERでは,Invertまでは完了しているが,inverseの表示が出てこない.桁数も0, 0 のままになっている.どうも,BigInteger.Divideという関数の中で滞留しているようだ.Divideの引数の中で,BigInteger.Pow(b, keta)の計算に手間取っているのでははないか?InverseClickの中でも,DispParametorを実行している.これは余分な処理なのではないか?いや,DispParametorを実行しているのは,ここだけだ.もう一箇所あるが,これは単に初期表示しているだけだ.

ToBCDが結構重い処理になっている.どうも,Debug.WriteLineで糞詰まりしているようだ.InvertFuncが完了した後で,小数を整数化→文字列化しているが,InvertFuncの中でこの数字列を取得することはできないのだろうか?この数字はとても巨大で,Debug.WriteLineですら表示できないような数だ.また,その間,点滅がまったく止まってしまうというのもおもしろくないところだ.valueが7桁の1234567なら,妥当な時間で表示まで進める.

延べ来訪者数がいつの間にか11万人を超えた.ちょっぴりうれしい.

image

循環周期列とInvertの内部コードを比較してみよう.⇒確かに一致している.つまり,InvertFuncを実施すれば,その結果を使って循環周期列を直接生成できる.循環周期列の生成は巨大数を用いたコストの掛かる処理だったので,これが省けるメリットは大きい.まず,DispInvertに相当する関数を作ってみよう.⇒従来論理の出力と比較してみたが,…

ψ関数のテーブルをハッシュ化した

Psi関数を書き換えて,配列サイズが整数範囲を超える場合には固定サイズ配列ハッシングするように修正した.これでかなり大きな数字まで(時間が掛かるのはやむを得ないとしても)処理できるようになった.ここで,Psi関数の仕様上の疑問が湧いてきた.現行インプリメントはψ関数の定義を満たしているのか?アルゴリズムは必ずしも定義に沿ったものにはなっていないように見えるが,これで正しいのか?この値は「b^x≡1 mod n」を満たす最小のxということになっているが,この式が成立するための条件がある.その辺りは押さえられているか?

9桁くらいまではそこそこ動作するが,それ以上になると数を入力しただけでほぼハング状態になってしまう.PSIで手間取っている.num=1234567890 b=10 arraysize=536608768だ.PSIはそれほど時間を消費しないと考えられていたので,プログレスバーも設置していない.しかし,Inverseはとっくに完了しているだが…Invertの方が重い処理のはずだったのではないか?10桁まではそこそこ動作する.11桁になると,PSIでなめくじになってしまう.num=12345678801 b=10 arraysize=536608768.Factoringでφ関数を使っているが,大丈夫だろうか?φは疑似素数でもb^φ≡b mod φ になる.

ともかくPSIが遅過ぎる.なんとかならないものだろうか?そもそも,現行ではPSI数は表示用にしか使われていない.どういうことだろう?一方,PHIは,①FactoringSub,②DispParametor,③SeedTestClick などあちこちで使われている.InvertFuncではいずれも使われていない.結局PSIはただの飾りということになる.PsiとInvertの論理はほとんど同じなので計算量にそれほど大きな差が出るのはおかしい.⇒InvertFuncはvalueが大きい場合には打ち切るようになっている.ψはつねに計算しているため,大きく見えていた.⇒同じ条件で打ち切るようにした場合には,ψの方がInvertより収束は早い.valueに11桁の数値を設定して,InvertFuncで例外が起きた.

image

配列RTでオーバーフローが発生している.これを避けるためには,PSIでやっているようにハッシュ化するしかない.⇒対処した.10進14桁までは進めるようになった.15桁になると流石に重い.⇒プログレスバーを出すようにしたら,10桁でもヒーヒー言っている.それほど影響あるだろうか?⇒確かに多大な影響がある.プログレスバーの代わりになるものはないだろうか?⇒ラベルの長さを変えてプログレスバー代用とするというアイディがネット上にあった.もう少し簡単なものが欲しい.タイマーで文字色を変えるというのもある.

中断ボタンを点滅させるというのが一番適切だが,画像を使っているので背景色の変更はできない.タスクバー上のボタンやタイトルを点滅させることはできるようだ.これがよいかもしれない.FlashWindowExという関数がある.⇒確かに,サンプルコードで点滅できた.ただし,VSのボタンが点滅している.また,停止したときに色が残ってしまっている.⇒GetMainWindowHandleの引数が”devenv”になっていた.”kinai”に変えて正しく動作するようになった.停止したときも元の色に戻っている.これがいい!プログレスバーは光線が横切るようなアニメになっていて,カッコいいのだが,廃止しよう.

https://atmarkit.itmedia.co.jp/fdotnet/dotnettips/723flashwindow/flashwindow.html

なぜだろう?SeedTestでは長いシーケンスに入っているのに点滅しない.Invertでは一度だけ点滅している.カーソルの切り替えは動作している.⇒原因はわかった.DoEventsが入らないと動作しない.15桁くらいまでは動作するようになった.ただし,InvertではB=1はテストしないようにした.B=1では固定列が長くなり過ぎる.

もう少し,仕様変更したい.inverseという値は現在一番興味があるところなので,この値を検定ボタンを押さずに更新したい.リターンキーで受け付けるというのがよいのではないかと思う.従って,テキストボックスの値を変更しただけでは更新されないというのでよいのではないか?値が確定するまでは待たなくてはならないが,Invertを押すと大きい数字の場合には無闇に時間を空費してしまう.

B進数循環小数表示

かなり仕上がってきたのだが,問題が出てきた.基数1のときの動作がおかしい.B=1でInvertを実行すると,n=200のとき,進数表記の値が空(/1:&/)になってしまう.これは本来なら,(/1:0000…1&)となるべきところだ.つまり,199個の0のあとに1という固定部を持ち,循環部なしという形でなくてはならない.これは,ペアノの公理で自然数を定義するために導入された後者関数の構成にかなり似ている.

自然数:後者関数 1進数表記

0:0 0
1:s0 1
2:ss0 10
3:sss0 100
4:ssss0 1000

自然数の逆数 1進数表記 1進循環小数表示

1/1:1.0 
1/2:0.1 /1:1&/
1/3:0.01 /1:01&/
1/4:0.001 /1:001&/

B進数循環小数表示とは以下のような形式の文字列である.

/B:xxx…/yyy…/

ここで,Bは基数を10進数で表示したもの,xxx…は小数非循環部のB進数表記,yyy…は小数循環部のB進数表記.B進数表記では,{0, 1, 2, 3,…9, A, B, C,…Z, a, b, c,…z, {, |の64個のアルファベットが用いられる.B>64の場合のアルファベットをどうするか?また,整数部を持つ小数をどう表現するかについてはまだ確定していないが,この記法を用いれば,任意の基数で循環小数の値を構造的に明示することができる.

基数が2以上の場合の動作は確認できているが,1の場合は暫定的にパスしているので,改めて考える必要がある.2023/04/13のログには,「n=1というのは,1/nが1になるというかなり特殊な数字だ.”循環小数=0.” + nnstrとあるように,ここでは1/nが1より大きくなることを想定していない.⇒暫定的にn=1の場合はエラーを回避して抜けるようにした.」としているところだ.

1進数表記した自然数同士の加算は可能であるから,定義としてはこれで正しいと思われるが,整数部を含む小数の表記が確立していないのは不都合だ.⇒単純に小数点を導入すればよいのではないか?整数部というのは非循環部の一部であり,非循環部で小数点を用いるようにすればそれで問題は可決する.つまり,たとえば,1.5という数をB進循環小数表示すれば,/1:1.00001&/となる.

&で止まっているということは,循環しないことを意味する.これですべての(正の)有理数を表記できるようになった.明らかに無理数はこの表記にはなじまない.非循環部が無限大の長さを持ってしまうため,正確な値をこの方法で表示することはできない.近似値として表示するのはもちろん可能だが…(通常表記でもそれ以上のことはできない)

循環小数進数表記では冒頭の基数を10進数で表記しているが,これもB進数アルファベットで表示した方がよいのではないか?10進表記とB進表記が入り混じっているというのは感心しない.

1/200を16進数表示しようとして,InverseClickで例外が発生した.zerosupが-2になっている.⇒修正ミスだ.進数表記の論理を入れる場所を間違えていた.

できた!16進で1/200を表示すると,/G:0.0&147AE/ のようになる.ややクリティカルなのは,Gという文字は16進数のアルファベットには含まれていないという点だ.16進より上なら入ってくるが,16進で使われるのはFまでの文字だ.16進を意味する文字がGだというのはいまいち,ピント来ないかもしれない.

しかし,この定義でもややあいまいな点は残る.2進数は0と1で表示されるが,1進数でも0だけでは表示できないと考えられるからだ.この意味ではやはり,1進法というのはかなり特殊な進数であると考えられる.16進をFとして表示したらどうなるか?それも分かりづらい.2進数は1と表示されてしまう.従って,16進をGと表記することは正しい.

1進数と2進数で使うアルファベットが同じというのも多少の違和感は残るが,最小限0と1がなければ数字を表記できないことは明らかであるから,やむを得ないだろう.0の個数だけで表記ということも考えられなくはないが,それだと,0が無限個並ぶような場合,判別できなくなる可能性がある.さて,一応収まったので,本題に戻ろう.1進小数の循環進数表記だ.まず,3という数の逆数1/3が表示してみよう.

固定桁,循環桁いずれも0になっている.結局,InvertFuncの計算が誤っていることになる.InvertFuncの論理には誤りはないはずだが,B=1では動作しない.この関数ではb^nをnで割るという操作を行っているが,b=1なので,b^n=1で変化しない.従って,これをnで割っても同じ結果にしかならないから,ループを空回りして空を返しているのだろう.どうすればよいか?大きくならないのだから,nで割るチャンスがない.これを回避するには,引き算しかないのではないか?つまり,除算の代わりに減算するしかないような気がする.修正して以下のような文字列が出てきた.

/:0.00&/

1/3:0.01 /1:01&/ だから,最後の0が1にならなくてはならない.この値はどうやって得ているのか?InverseClickではb^ketaを計算して10000…のような数を作り,それをnで割る操作で1*b^k/nを求めているが,BigInteger.Divideは整数除算で1/nを実行することになるので,nn=0となってしまう.n=1の場合は例外として扱われている.これは1/1は基数bの値に拘わらずつねに1になることによる.この関数の中でnnstrを生成しているので,ここでその答えを作り出してやるしかない.

できた.ほとんど仕上がったのではないか?あとは,3種検定の出力を整理するだけだ.この出力は必要に応じて随時改変すればよいので,とりあえず,最小限の情報を整った形式で出力することを目標とする.

剰余周期列検定でminよりmaxが小さいと何も出力されない.一度は実行するという方がよいのではないか?⇒対処した.

▲valueに巨大数を入れたら,落ちた.以下は呼出履歴

Microsoft.VisualBasic.Conversion.Val(string)
Kinai.Kinai.ValueChanged() 場所: Kinai.vb
Kinai.Kinai.num0_TextChanged(Object, System.EventArgs) 場所: Kinai.vb
System.Windows.Forms.Control.OnTextChanged(System.EventArgs)   
System.Windows.Forms.TextBoxBase.OnTextChanged(System.EventArgs)
System.Windows.Forms.TextBoxBase.WmReflectCommand(ref System.Windows.Forms.Message)
System.Windows.Forms.TextBox.WndProc(ref System.Windows.Forms.Message)
System.Windows.Forms.Control.ControlNativeWindow.WndProc(ref System.Windows.Forms.Message)
System.Windows.Forms.NativeWindow.Callback(System.IntPtr, Interop.User32.WM, System.IntPtr, System.IntPtr)
System.Windows.Forms.Control.ReflectMessage(System.IntPtr, ref System.Windows.Forms.Message)

テキストの長さは6689で上限32767にはほど遠い.Val(num0.Text)でテキストを数値に変換したところで落ちている.受け側はBigIntegerなので受けられるはずなのだが…System.OverflowExceptionが起きている.BigIntegerにはParseという関数がある.これを使ってみよう.⇒The value could not be parsed.というエラーが出た.空文字列では例外が発生する.これはずいぶん厄介だ.⇒BigValというラッパを作って回避することにした.しかし,その後のFactoringSubで,BigInteger cannot represent infinityという例外が発生する.

Math.Sqrtで落ちている.BigIntegerに代替関数はあるだろうか?BigInteger.Sqrtという関数は存在するようだが,どうも.NET Proffessionalでないと搭載されていないような感じだ..NET 3.5が必要ということのようなので,.NET 6.0をダウンロードしてみた.(最新版はすでに7.0だが,敬遠した)インストール完了時に「このソフトは使用状況を収集します」というメッセージが出た.そんな話聞いてないぞ!

Extreme Optimization Numerical Libraries for .NETはやはり,有料だった.2ヶ月間の無料トライアル版というのはある.以下のURLにBigIntegerを使った平方根の計算コードが載っていた.多少の弱点はあるようだが,使えないというものではないようだ.試してみよう

https://www.codeguru.com/visual-basic/using-biginteger-in-visual-basic-2010/

このサイトの説明にも書いてあったが,ゼロ除算が発生した.整数範囲の数ではmath.sqrtで解くように改造して解決した.FactoringSub,Division,ConvertClick,DispParametorをクリアして,InverseClickで例外が置きた.Value was either too large or too small for an Int32.というものだ.いや,違う.DispParametorだ.PSIsuをLongにしておいたのがまずかったのかもしれない.⇒いや,psi関数の中だ.RTとITという配列を使っているが,そのサイズが大き過ぎたようだ.

進捗をみるためにプログレスバーを導入した

プログレスバーを導入したのだが,どうも動作が思わしくない.初期起動で少しだけ進んだ状態のまま止まってしまう.⇒進捗率6%で抜けてしまっている.⇒ループから横道に抜けていた.基数の情報(約数)などを知りたいのだが,常時画面に出すのではなく,Invert出力でよいのではないか?表示されるべき項目には,基数:素因数分解,nとのGCM,bのレピュニット数など.

CASIOのサイトでφ関数が計算できる.その結果と出力が一致していない.n=1234567のとき,CASIOではφ=1224720となっているが,KINAIでは41088が出力されている.Wolframでも同じ数を出しているので,こちらが間違っているのだろう.φの計算はFukuzo氏に紹介されたものをそのまま使っているつもりなのだが…オリジナルのコードは残っているだろうか?⇒オリジナルのコードに戻してみたが,結果は同じだ.1234567は1, 127, 9721, 1234567しか約数を持っていない.従って,1と1234567を除けば,127, 9721, 127×9721の3つしかない.いや,これらの倍数で1234567より小さいものも含まれるから,実数はもっと大きい.確かに41088という数字は小さ過ぎるような気がする.

オリジナルのコードは新潟大の竹内研究室からのコピーだし,最近のものは,奥村晴彦著『c言語による「アルゴリズム辞典」』が出典だ.2つとも間違っているというのはかなり考えづらい.加工の仕方が悪いのだろうか?確かに古いコードでLongという整数型を使っているのは問題かもしれない.それもあるが,PFactorをsieveを使わないように改造したことも影響している.PFactorは小さく約数から返すようになっているが,逆に大きい約数から返すようにしないと動作しないはずだ.オリジナルコードは廃棄してしまったが,sieveを使うようにするか,ないし,単純で非効率なコードに書き換えるしかない.

奥村のコードは少なくとも整数範囲では正しく動作しているので,こちらを改造して対応することにする.⇒なぜだろう?今度は正しい値がでるようになった.修正箇所としては,パラメータを表示している論理をInvertFuncの外に出したといことしかしていないのだが…いや,原因は分かった.InvertFuncは無茶苦茶時間の掛かる処理でまだφを計算するところまで進んでいなかったというだけの話だ.プログレスバーを取り付けてみたが,数分実行しても値はゼロからまったく変化していない.⇒カウンタを10000で割った剰余の1/100を出すようにして動作するようになった.10000点が1サイクルに当たる.

この論理の高速化は可能だろうか?この計算は循環周期が短ければかなり簡単に終わる場合もあり,周期がnに近いような場合にはとてつもなく時間が掛かってしまう.これは避けられない.⇒10000を1000に短縮した.この方が計算が速そうに感じるので心理的効果はある.これだと変化が速いので,10000点くらいまでは我慢できそうだ.いや,せいぜい5000点くらいかもしれない.値の更新では途中で打ち切ることにする.3000くらいで十分なのではないだろうか?⇒いや,もっと短くてもよい.大きい数字の場合にはInvertを使うという仕様だ.

逆数周期表示を見易くするために,記号の前後に空白文字を入れてみたが,コピーするとき切れてしまうので,空白を入れないように変更した.また,この行に固定部と循環部の桁数を出すようにした.これらの値はInvertFuncが最後まで実行されないと与えられない.処理が中断された場合には0, 0 となる.

だいぶいい感じになってきた

だいぶいい感じになってきた.特に,B進数⇔10進数の相互変換が自在にできるようになったのがうれしい.これは相当役に立つと思う.循環小数は基数が決まらないと意味がないので,基数を変化させることができることはその辺りを調査するときに使うツールとしては必須の機能だ.ここまでやると,Invertを実行しなくても,逆数の循環単位などを常時表示できるようにしたくなってくる.整数Nの逆数である循環小数Dの固定部Xと循環部Yを2つの整数とみなすと,XのB進数表記の桁数をx,Yの桁数をyとすれば,0≦x, y<N,0≦X<B^x,0≦Y<B^yで,

D = X / b^x + Y * ρ(x, y) (1)

ここで ρ は ρ(x, y) = Σ{k=0→∞}(1 / {B^y}^k) / b^x のような無限級数.(1)式はどんな小数にも適用できる等式だが,桁数 x, y が不定というところが厄介なところだ.4093という素数をB=11で逆数を取ったところ,循環単位の桁数が2046になった.ρ(x, y) は無限等比級数で,r=1/B^y < 1 により収束する.Σ{n=1→∞}a_n = a_1/(1 – r) .これが正しいとすると,1 – r という数がどのようなものであるのかが気になる.この値を計算するには,B^y という数を決定し,その逆数を取って,それと1の差分を計算する必要がある.どうもこの当たりが鍵になりそうな気がするので,実装を試みることにしよう.

電卓としても使えるようにn^pの計算で剰余だけでなく計算数値も出すようにした.循環小数値をX&Yの形式で表記することを考えてみる.たとえば,252_10であれば,00&390625のようになる.つまり,1/252 = 00&390625(10)と表記できる.この表記では頭のゼロは落とせないので,/00/390625/10とするのがよいのではないだろうか?あるいは,10/00/390625の方がベターかもしれない.⇒このような値を与えられたとき,これから1/252という元の数字を導くことができるだろうか?

InverseClickでエラーが発生した.n=255, b=12のとき,固定桁 fixed=1, 循環桁 k=16で,1+16*2=33桁の数字列を取り出したあと,zerosup = keta – nnstr.Length が –4 という負値になったため, New String(“0″c, zerosup)でエラーが発生した.nnに入っている値は,{1608573608807851864064416092523532}という大きなもので,b^keta / n の値だが,ConvertNum2String でテキストに変換したとき,桁数が37しか取れなかった.

ConvertNum2Stringが誤動作しているようだ.間にNULLキャラが入っているように思われる.いや,”A8”とか,”BA3”のような複数文字がつながった部分がある.⇒エンコードの問題だ.UTF8を使っていたが,UNICODEに変更して動作するようになった.

System.Text.Encoding.Unicode.GetString(BitConverter.GetBytes(c))

SeedTestでWRONG TOTIENTが出ているが,これは何だろう?「pk <> k And tot > 1」という理由だ.tot はφ関数,kは循環単位長,pkはtotとkのGCMだ.SeedTestは1~Nの範囲で検定を行い,整数の属性をチェックしている.pk=2, k=0, tot=2だ.対象数は4で基数は10.⇒ツールで常時φやψが見えるようにしておこう.

InverseClickで「R <> b And R <> 1」で停止した.R=0, b=20, b=128.⇒今度は,R=4, b=10, n=12 で停止した.InvertFuncではまずx=b=10として,x\n=10\12=0…10.次にx=x*b=10*10=100として,100\12=8…4,次に,x=R=4で,x*b=4*10=40\12=3…4.このRは既出だから,循環が閉じて復帰している.この計算は正しい.つまり,循環が閉じるときのRはbや1に限った話ではない.従って,ここで停止する必要はないと言ってよい.

ファイルを開こうとして,競合エラーが発生する.これはおもしろくない.⇒エラートラップを仕掛けてresumeするようにした.⇒ファイルに保存をオプションとする.

InverseClickで「ERROR:Count cannot be less than zero. (Parameter ‘count’)」というエラーになった.zerosupが-1になっている.上で出ていた症状だ.nnstr.Length=2でketa=1のため,差分がマイナスになってしまう.nnstrには”10”という文字列が入っている.nnも10だ.fixed=1でkが0であるため,keta=1+2*0で1になっている.n=1という数が入っている.n=1というのは,1/nが1になるというかなり特殊な数字だ.”循環小数=0.” + nnstrとあるように,ここでは1/nが1より大きくなることを想定していない.⇒暫定的にn=1の場合はエラーを回避して抜けるようにした.

▲φφというパラメータをチェックする必要があるだろうか?この値はφ(φ())で,nのトーシェント関数のトーシェントだから,nを変えない限り変化しない.

▲ψがゼロになる場合がある.このようなときは,循環桁数=φになる.通常は,φ≧ψでψ=循環桁数になっているのだが…これは調べておく必要がある.どうもBの約数と関係があるようなので,Bの約数も表示できるようにするとよいのだが…

ToBCDで例外が発生している.以下の計算式で発生する.

Dim byteCount As BigInteger = Math.Log(val) / Math.Log(b) + 1

n=255と小さな数字だが,逆数を整数化した数は巨大数になる.3921568627450980392156862745098 ToBCDでは冒頭で配列サイズを決めるためにMath.Logを使っている.対数計算しないように方式変更した.⇒最初にInt16.MaxValueサイズの配列を確保し,これを使って直接n\bの剰余(BCD値)を格納して桁数をカウントするようにした.

だいぶ整ってきた

だいぶ整ってきた.

image

対象数値ないし除数,基数を変えると自動的にボックス内の数値を更新するようになっている.除算を実行して余りがある場合にはGCMは1より大きく,割り切れるときにはGCMは除数そのものになる.notationの欄ではB進表記した数を入出力できるようにしたいのだが,まだ実装されていない.画面下部の剰余数列のブロックではkないしnをある範囲で変化させて周期数列を生成しているが,単点のn^p mod k という値を取り出したい場合もあるので,個別に計算できるようにした.ボタンの数は大幅に減って上段では,①PrimeTest, ②SeedTest, ③Invert と④Clear だけになった.これらの処理の内容はまだかなり整理が必要だが,大枠は完全に固まったといってよい.

対象数値をLongの範囲とするという制限は撤廃することにした.どうしても制限が必要な場合は出てくるかもしれないが,原則として無制限としておきたい.重くなる原因としてダンプ文字列が長くなることがあるかもしれない.コラッツのときは文字数制限してある分量を超えると捨てるようにしていたが,かなり効果があった.ただし,ファイル出力を選べばダンプをファイルに保存できるようになっていたので,その機能は必要かもしれない.出力パネルはもう少し横幅があった方がよい.

InvertFuncはPrimeTest, SeedTestからも呼び出している.ダンプの量が多いので,Invertコマンドの場合以外はこれらの値をダンプしないようにした.ただし,ファイルには出力する.逆数の循環数列を設定パネル上に表示して Invertボタンを廃止することも考えたが,対象数が4桁を超えると相当な桁数になってしまうので,現実的ではない.詳細はInvertボタンで表示し,PrimeTestやSeedTestでは隠蔽するというのが妥当だ思う.ディテールはまだまだ整備しなくてはならないが,最後の関門 notationへの変換・逆変換をやっつけてしまうことにしよう.

Convert.ToStringは基数が2, 8, 10, 16の場合しか扱わない.それ以外では例外が発生する.これは自前で作るしかない.ToBCDという関数も思ったような動作にならないので,丸ごと書き換えた.⇒動くようになった.かなりおもしろい.基数の範囲は2~62とした.アルファベットのA~Zとa~zに別々の値を与えて,最大でzzzzzzz…のような数まで表示できる.あとは,これを表記から数値に変換する処理を組み込むだけになった.ただし,こちらはユーザ入力から数値に変換するので,エラーに対処する必要がある.

いや,このエラーは無視してもよい.特に動作上のエラーにはならない.たとえば,2進数列に2という数字が紛れ込んだ場合には,2×2の値がその桁にあるとして計算するだけだ.10進に戻って,もう一度2進で表示すると正しい2進数列になっている.

16という数が入力できない.(6をBSで消去して再入力しようとして)1はBのレンジに入っていないため,弾かれてしまうようだ.⇒1を範囲に加え無処理で抜けるようにした.

N進数への変換・逆変換はほぼ仕上がったようだ.基数は最終的に2~64まで対応ということにした.62でzまで使い切るので,64の場合には{と|が余分に使われる.もし,その進数の範囲を超える文字が入力された場合には,直ちに変換して正しい数字列に書き換わるので,その文字が使えないことを指摘しなくてもよいだろう.あと,残った課題は,①3種の検定の出力を整理して使い易いものにする.②巨大数でハングしないように適切な例外処理を入れる,の2点だけになった.そのあとは,このツールをどう活用するか?というフェーズに入るが,おそらく因数分解の効率化というところから入ることになるのではないかと思う.相当強力なツールになったので,役に立つと思う.

3種テストの方はすべて出力をファイルに保存できるようになっているが,剰余の方は残っている.こちらも保存できるようにした方がよい.ただし,こちらはあまり長いダンプは出ないので,画面からコピーするだけでもよいかもしれない.ファイルを開いて追加出力できればよいのだが…惜しむらくは,文字が少し小さ過ぎるという点ではないだろうか?いまさらフォントサイズを変えるという訳にもゆかないが,もう一回り大きければだいぶ楽だったのではないだろうか?⇒完成間近なのでアイコンを見つけなくてはならない.⇒いまいちパッとしないが,これ「 image 」 でいくことになった.