Hatena::ブログ(Diary)

玄天黄地

2011-11-07

脳内計算尺

| 22:43

 以前、計算尺相当の有効数字での計算ならば指数関数を除いて暗算可能だ、という話をしたことがある。

 捜し物をしていて、偶然、そのことを記したメモを見つけたので、忘れないうちに転載しておく。


仮定)

脳内に、一時記憶領域(以下、「レジスタ」という)が7つある。

角度は、度分秒で与えられる。

3桁×1桁の乗算、5桁程度の加算は、一時記憶領域を必要とせずに実施できる。

(最後の条件だけは、ちょっと厳しいかも。暗算4級(珠算の)を要求している。)

結論)

計算尺と同等の精度で三角関数の計算ができる。


手順:

Use R4, R5, R6, R7 4番から7番までのレジスタをアキュムレータとして使用する

 

Mov R1, degree   1番レジスタに角度値(まだ度分秒)をロード

Mov R2, C_PI    2番レジスタに円周率の値をロード

Mul R1, R2     1番レジスタに2番レジスタの値を乗算

Mov R2, 180     2番レジスタに180(定数)をロード

Div R1, R2     1番レジスタを2番レジスタで除算(これで角度が弧度法に)

 

 角度を弧度法に変換している。円周率を乗ずる際には、筆算だと3桁×3桁で、乗算記号の下に4段の数字が並ぶので、4つのレジスタを計算途中の一時記憶用として使用する。

 言い換えると、3桁×1桁の乗算は、脳内レジスタを消費せずに計算できなければならない。また、小数の位取りは、自分で調節しなければならない。

 

       258   1番レジスタに格納済(実際には様々な値)

    x   314   2番レジスタに格納済(円周率の最初の3桁)

    −−−−−−−−−

      1032   4番レジスタを使用

      258    5番レジスタを使用

     774     6番レジスタを使用

  −−−−−−−−−

     81012   7番レジスタを使用 → 1番レジスタに再格納、

 

 このとき、有効数字4桁目以降の四捨五入と、小数位置の確認を同時に行っている。

 

Mov R2, R1

Mul R2, R1     2番レジスタには角度xの2乗が格納される

Mov R3, R2

Mul R3, R1     3番レジスタには角度xの3乗が格納される

 

 このとき、いすれも4番〜7番レジスタが、第一段の場合と同様に、計算途中結果の格納用として使用されていることに注意。

 

Free R4, R5     4番及び5番レジスタをアキュムレータとしての役割から解放する

Mov R4, R3

Mov R5, 6

Div R4, R5     4番レジスタには x3/6 が格納される

Sub R1, R4     1番レジスタに、x−x3/6 が格納される

Use R4, R5     4番、5番レジスタを再度アキュムレータとして使用する

Mul R2, R3     2番レジスタには角度xの5乗が格納される

Mov R3, 120

Div R2, R3     それを120で割って、2番レジスタの値が x5/120 となる

Add R1, R2     1番レジスタに2番レジスタを加える。これは殆ど不要であることが多い。

Free R4, R5, R6, R7 アキュムレータを解放して

 

return R1      終わり。1番レジスタに、有効数字3桁で、sin X が格納されている。


備考)

Cos も、基本的には計算の手間は同じ。

Tan は、計算量がもう少し多くなるので多少厄介。

Log は、log102(0.3010)、log103(0.4771)だけを覚えていれば、あとは素因数分解の組合せで暗算可能。

→ log10325 の場合、

  325=5×5×13、

  log105 = 1−log102 = 0.6990、

  log1012 = 1og102+1og102+1og103 = 0.3010+0.3010+0.4771 = 1.0791

  log1013.3333 = log1040−log103 = 1+1og102+1og102−1og103 = 1.1249

  log1013 ≒ 1/4・log1012+3/4・log1013.3333 = 1.1134(実際は1.11394)

  log10325 = log105 + log105 + log1013 = 0.6990+0.6990+1.1134 = 2.5114

  で、有効数字を3桁に丸めて、log10325 = 2.51(実際は2.51183)

Exp は、早い収束級数がないので、計算不可能。

→ 1時間くらいかかってもいいなら、以下のやり方が一応存在する。

  (1) Ab=P として、

  (2) log10P = log10Ab = b×log10A

  (3) log10A を求め、それをb倍してlog10Pを求める。

  (4) 適当な数字xについてlog10xを求め、log10Pと比較する。

  (5) log10xの値がlog10Pとほぼ等しいときは、P≒x である。(計算終了)

  (6) log10xの値がlog10Pより小さいときは、xを大きくして(4)へ戻る。

  (7) log10xの値がlog10Pより大きいときは、xを小さくして(4)へ戻る。

 

問題点

 これらの手法、特に最後の Exp は、計算量が膨大なため、脳内レジスタの疲労によるメモリ揮発が心配である。Geo80k のように中高年になってしまうと、特にメモリリフレッシュで苦労する。

 アルゴリズムもエレガントの対極である。(4)〜(7) までのループがひどい。

トラックバック - http://d.hatena.ne.jp/Geo80k/20111107/1320673406