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という配列を使っているが,そのサイズが大き過ぎたようだ.

コメントを残す

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

CAPTCHA