VBの文字列→数値変換関数Val()で奇数が偶数に化けてしまう

書きかけでPCを再起動することになったので,下書きに保存してOpen Live Writerを閉じたつもりなのに,残っていない.パラグラフ3つ分くらいなのだが… 最初の辺りはもう忘れてしまったので,最後のVBのバグについてだけ書いておこう.

DIm N as Ulong = Val(str) で文字列を数値に変換するとき,Integerの上限よりも大きいがUlongの上限よりは小さいような奇数文字列を変換しようとすると,偶数に化けてしまう.境界がどの辺りかは確定できなかったが,10進数で15桁以上の数で起きているように思われる.Valを使うのを止めて,Ulong.parse()を使うように変更して解決した.

▲9007199254740991という奇数のコラッツ木上のアドレスを計算して,下のような結果が出ている.

3 [1]  5 [1] 1 [1]

これはかなりおかしい.3は3の倍数であり,3の倍数は部分木を持っていないことになっているからだ.しかも,3 [1]というのは3というノードの枝1に接続していることを意味するのだから,なおさらだ.

9007199254740991 – 1)  = 9007199254740990 を4で割ると,2,251,799,813,685,247.5 余り 1 になる.従って,このノードは最右ノードであると思われる.この数に 3N+ 1 を施すと,27021597764222974を2で割り込んでゆくと,3になる.この計算はおかしい.27021597764222974は3の倍数ではない.どうもN/2の計算が間違っているようだ.実数になってしまっている.⇒2で除算する代わりにビット演算で右シフトするようにしたら正しく動作した.ただし,どこかでオーバーフローが発生してしまう.3N+1でオーバーフローが起きている.ノードの枝ポジションの計算は単発なので,ここで打ち切るしかないだろう.

上記の修正をプログラム全体に適用しなくてはならない.①ValをParseに代える,②N/2を右シフトに代えるの2点だ.⇒この修正後,起動時に例外が発生するようになってしまった.どうも,Parseという関数はテキストが空文字列の場合には例外を発生するという作りになっているようだ.しかし,デザイン画面では13という値が入っているのだが… この例外はDesigner.vbでオブジェクトの初期化を実施しているところで起きている.TextBox1_TextChangedで文字列が空の場合は無動作で復帰するようにした.

2で除算で動作不良が起きるのなら,他の数での除算でも同様のことが起きる可能性がある.このプログラムでは除算は①2で除算,②3で除算,③4で除算,④d-1 で除算の4通りある.③の4で除算は右シフト2回,③で除算は右シフト+加算でも対処できるが,④が問題だ.しかし,④は問題にならない可能性もある.2で除算でエラーが出るのはおそらく,システムが型の異なる2つの値の除算と判断して,倍精度実数演算に切り替えているためではないかと推定される.これはおそらく定数2をIntegerと推定しているためと思われる.d-1の場合はdがULongなので,多分d-1もULongと認めてくれるのではないか?

③で除算は右シフト+加算でも対処できるというのは,×3と÷3を取り違えている.3で除算をビット演算で代用することはできない.⇒安全のため,定数3をULongとして定義して使うようにした.

大体できたので,動画を取ってFBに投稿した.

https://www.facebook.com/groups/2354748741306929/posts/4541797995935315/?comment_id=4644516072330173&reply_comment_id=4644558065659307&notif_id=1640091947682768&notif_t=group_comment&ref=notif

コメントを残す

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

CAPTCHA