ワンボードマイコンをつくろう!(パソコンの原点はここから始まった)
TK80ソフトコンパチブル!8080、Z80マシン語からBASICまでこれ1台でこなせます
当記事は2009年11月から「TTLでCPUをつくろう!」というタイトルの もとにほとんど毎日連載をしてきたものを再編集したものです。 2011.7.1
前へ
次へ
目次へ戻る
ホームページトップへ戻る
☆ND80ZVでBASICを(2)
ND80ZVに搭載予定のBASICはハンパではありません。
浮動小数点演算をこなし、さらに三角関数、対数計算までできるのです。
しかも、倍精度での演算もできてしまいます。

[第69回]

●LOGとLN

Z80BASICの実数演算のサンプルプログラムで、最初にSQR()関数とべき乗について説明をしまして、次に三角関数SIN()、COS()、TAN()の説明をしました。
そうしますと、次はやっぱり対数関数ということになりますでしょう。

なので今回はそのLOG(常用対数)とLN(自然対数)について説明をいたします。
ええ。
Z80BASICには、常用対数も自然対数も、備わっているのです。

まあ、今こうやってあらためて、対数関数の説明をしようとして、よくよく考えてみますと、はて、BASICでLOGなど何に利用できるのだろう?
と疑問を感じてしまいます。

なんでもその昔、計算機などという便利なものがなかった時代には大きな桁数の乗算や除算は大変な労力を必要としたはずで、そのために対数という便利な概念が考え出された、と伝えられております。
とにかく大きな数値同士の乗算、除算で、概算でもよいのだけれどそこそこ正確な答えが欲しい、という場合に、対数を使うと、乗除算が加減算になってしまいますから、そりゃあ便利だったはずです。

ええ。
関数電卓の無かった昔でしたら、確かに。

ですけれど、今はわざわざ対数を使わなくても、大きな数の乗算でも除算でも、あるいは加減乗除が複雑に組み合わさった計算でも、コンピュータという便利なものがあるのですから、あっという間に計算できてしまいます。
おそらく、対数の出番などは無いのでは?

では、なぜに、Z80BASICには、わざわざ苦労してLOG()関数やLN()関数があるのでしょうか?
いや、正直なところ、私自身が疑問に思います。

なぜかといいますと、このZ80BASICを作り上げた当時、そのころはBASICの全盛期でありましたが、他社のBASICを見ますとちゃんと対数関数があるものですから、それならウチでも入れておかにゃあまずいだろう、ということで、それ以上深くは考えないで、LOG()もLN()も使えるようにしてしまったと、多分そのような理由だったのではないかと思います。

まあ、そういう次第で、LOG()やLN()などは、いまどき余り出番の無い関数かも知れませんが、せっかく作ってある機能ですから、ここでご紹介させていただくことに致します。

まずはいつものように単精度実数型のサンプルプログラムです。

>list
    10 FOR A=1 TO 10
    20 PRINT A,LOG(A),LN(A)
    30 NEXT A
>run
1            0            0
2            0.30103      0.693147
3            0.477121     1.09861
4            0.60206      1.38629
5            0.69897      1.60944
6            0.778151     1.79176
7            0.845098     1.94591
8            0.90309      2.07944
9            0.954242     2.19722
10           1            2.30258

たった3行だけの簡単なプログラムです。
昨今はねこもしゃくしもCばかりで、BASICなど見向きもされないようでありますが、この簡便さこそがBASICの一番のウリなのです。
BASICと言いましても、その昔のPC8801とかPC9801の時代のBASICのことで、Visual Basicなどではありません。
昔のBASICは簡便で実に使い易かった、と思います。

さて、上では1〜10の間の常用対数LOG()と自然対数LN()を求めています。
で、この値が正しいかどうか、ということなのですが、LOG()もLN()も三角関数と同様にEXCELで計算して求めることができます。

どうせ、EXCELで求めた結果と付き合わせて評価しよう、ということでしたならば、単精度の計算ではなくて、やっぱり倍精度で計算させた結果とEXCELでの計算結果を比較させてみたいですよねえ。

そこで、今度は倍精度実数演算のLOG()とLN()の計算結果を求めてみました。

>list
    10 FOR A#=1# TO 10#
    20 PRINT A#,LOG(A#),LN(A#)
    30 NEXT A#
>run
1            0            0
2            0.3010299956639812        0.6931471805599454
3            0.4771212547196624        1.09861228866811
4            0.6020599913279624        1.386294361119891
5            0.6989700043360187        1.6094379124341
6            0.7781512503836435        1.791759469228055
7            0.8450980400142567        1.945910149055313
8            0.9030899869919435        2.079441541679836
9            0.9542425094393248        2.197224577336219
10           0.9999999999999999        2.302585092994046

あれ。LOG(10)の計算でわずかな誤差が出てしまいました。
あくまで近似値で計算を行っていることと、10進数ではなくて2進数で計算をしているために、10進数ではきちんと割り切れる数でも、2進数では誤差が残ってしまうことがあります。
実用上は全く問題無い値なのですけれど、このままではちょっと見た目が悪いので、内緒で補正することにいたします。
また、三角関数のときもそうでしたが、倍精度実数演算の計算結果は表示桁数が多いので、縦がきれいに揃わないところが出てきます。そこのところもちょいとPRINT文に手を加えてみました。

>list
    10 FOR A#=1 TO 10
    20 IF (A#=1)PRINT \5;A#,:PRINT LOG(A#)," ",LN(A#):GOTO 50
    30 IF (A#=10)PRINT \5;A#,:PRINT LOG(A#)+0.1D-15," ",LN(A#):GOTO 50
    40 PRINT \5;A#,:PRINT LOG(A#),LN(A#)
    50 NEXT A#
>run
    1        0                         0
    2        0.3010299956639812        0.6931471805599454
    3        0.4771212547196624        1.09861228866811
    4        0.6020599913279624        1.386294361119891
    5        0.6989700043360187        1.6094379124341
    6        0.7781512503836435        1.791759469228055
    7        0.8450980400142567        1.945910149055313
    8        0.9030899869919435        2.079441541679836
    9        0.9542425094393248        2.197224577336219
   10        1                         2.302585092994046

ご覧の通りの結果が得られました。
LOG(10)だけは、きちんとした値にして表示するために、結果に0.1×10−15を加えています。
倍精度で数値を指数表現するときは、0.1D−15というようにします。
なお0.1E+5のようにEを使うと実数型定数になります。

では、これをEXCELでの計算結果と照合してみましょう。
EXCELでの計算結果です。

a	   log	                  ln
1	0.0000000000000000 	0.0000000000000000 
2	0.3010299956639810 	0.6931471805599450 
3	0.4771212547196620 	1.0986122886681100 
4	0.6020599913279620 	1.3862943611198900 
5	0.6989700043360190 	1.6094379124341000 
6	0.7781512503836440 	1.7917594692280500 
7	0.8450980400142570 	1.9459101490553100 
8	0.9030899869919440 	2.0794415416798400 
9	0.9542425094393250 	2.1972245773362200 
10	1.0000000000000000 	2.3025850929940500 

おお。ぴったりではありませんか。
と、言いたいところなのですが、ちょっと気になるところがあります。
LN(6)は、Z80BASICでは末尾が…8055なのに、EXCELでは…8050になっています。
まあ計算末尾だけのことですし、このあたりは誤差の範囲と考えてもいい、と思いますから、無視してもよろしいのですけれど…。
念の為に、Windowsの関数電卓で計算してみました。

さすがに、有効桁数が違いますねえ。すごいものです。

おお。末尾は、…8055になっています。
お、お、おー。という感じですねえ。
CPUをつくろう!第554回(2010.7.16upload)を再編集

ワンボードマイコンをつくろう![第69回]
2011.7.1upload

前へ
次へ
目次へ戻る
ホームページトップへ戻る