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と同じ数が入っている.かなり

コメントを残す

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

CAPTCHA