« 「2のn乗の数」の先頭の数字列:無限の恐ろしさ。:その1・話の概要 | トップページ | 「2のn乗の数」の先頭の数字列:無限の恐ろしさ。:その3・プログラム完成・実行結果 »

2016年2月25日 (木)

「2のn乗の数」の先頭の数字列:無限の恐ろしさ。:その2・プログラムの「バグ」にぶつかる。

「その1」で見通しを立てたその方針でプログラムを書きました。(仮称10進BASICで)

INPUT PROMPT "a = ":a
LET L2 = LOG10(2)
LET L = FP(LOG10(a))
LET R = FP(LOG10(a+1))

LET n = 1
DO
   LET w = FP(n * L2)
   IF(L <= w) AND (w < R) THEN
      EXIT DO
   END IF
   LET n = n + 1
LOOP
LET tmp = n * L2
PRINT "2 ^";n;"=";10^FP(tmp);"* 10 ^";IP(tmp)

END

{プログラム中「FP」というのは小数部を求める関数、「IP」は整数部を求める関数です。}

★そうしたら、まず7でしくじった。
先頭の数として「7」を指定すると、答えとして「2^3 = 8」が出てきてしまうんです!

このBASICの内部の演算精度のせいで、普通に実行したとき
プログラムの冒頭で、R = log(7+1) を求めると「 .903089986991944」となります。これが不等式の右。
ところが、演算時、n=3のときに「3 * L2」の小数部を計算すると「 .903089986991943 」こうなるんです。
そうすると、不等式が成立しまして、答えとして「2^3=8」が提示されるのですね。

変数の値を追跡してわかりました。
このBASICのオプションには「1000桁モード、超越関数使用」というのがあります。対数での1000桁は無理ですが、内部演算精度が上がります。これで「7問題」はクリアできました。
a = 7
2 ^ 46 = 7.0368744177664036 * 10 ^ 13
「2の46乗は7で始まります。」
{ヨカッタ}

★次に9でしくじった。
a=9 なら a+1=10 です。log(10)=1 ですので、小数部が0です。
そうすると
log(a) の小数部分 ≦ log(X) の小数部分 < log(a+1) の小数部分
この不等式の左は正の小数なのに、右が0ですから、この不等式が成立することは永遠にあり得ない。
で、「恐怖の無限ループ」に落っこちた、はまった。
仕方なくブレイクをかける。マイッタナ。

解決法:9とか、99とか、1を足して対数を取った時に小数部が0になる場合は、不等式の右を「1」にすればいいのです。
そうすると「1未満」となるので無限ループの罠は解消するはず。
そのようにして実行すると
a = 9
2 ^ 53 = 9.0071992547409972 * 10 ^ 15
「2の53乗は9で始まります」
{ヨカッタ、ヨカッタ}

★本の著者の数学者、根上さんはこの出来事を見落としてないか?と再度ちゃんと読んだら

・・・aが999…99である場合を除き・・・
その唯一の例外の場合は、a+1=1000…00となって、log(a+1)は半端がなくなり
log(a+1)-s=1
となります。・・・

ちゃんと指摘してありました。読者=私が見落としていただけでした。
「唯一の例外」ではあるのですが、この例外は無限個あるんですよ。おそろしいなぁ。

« 「2のn乗の数」の先頭の数字列:無限の恐ろしさ。:その1・話の概要 | トップページ | 「2のn乗の数」の先頭の数字列:無限の恐ろしさ。:その3・プログラム完成・実行結果 »

理科おじさん」カテゴリの記事

コメント

コメントを書く

(ウェブ上には掲載しません)

« 「2のn乗の数」の先頭の数字列:無限の恐ろしさ。:その1・話の概要 | トップページ | 「2のn乗の数」の先頭の数字列:無限の恐ろしさ。:その3・プログラム完成・実行結果 »

2017年9月
          1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
サイト内検索
ココログ最強検索 by 暴想
無料ブログはココログ