数学関数を作る                                vega 2003.10.08
                                              2003.11.26            


  H8でコンパイラに数学ライブラリーが付属していない場合下記の方法で作ることができます。
  三角関数の場合は、絶対値が360度(2π)以内になるようにして計算します。
  ロジックの検証は、パソコン側のCで行えば効率がいいです(実際の値と結果を比較する)。
  ただマイコン側とデータの内部構成の違い、その他でマイコン側で同じように動く保証はありませんが。
  精度は倍精度で。
  私の使用したコンパイラ(秋月Ver.1)は、fabsの値がデタラメなので自分で作りました。
  各関数はここに参考になるソースがあります(あるはず)。
  http://www.matsusaka-u.ac.jp/~okumura/algo/  
  
「奥村晴彦」さん著 『C言語による最新アルゴリズム事典』 の公開ソース

  
定義される範囲外のチェックや、きわどい値(定義の限界に近い値)まできちんと計算するのは結構めんどうです。
 
 私はいいかげんにやってます。

  
三角関数の(逆関数も)級数は、機械的10回しています。確か15桁程度の精度が出ました

1.数学関数

  (1) sin  下記 級数を計算

    

                    

  (2) cos  下記 級数を計算   

                        

  (3) tan  

    tanθ= sinθ/cosθ で計算( (1)、(2)を使用 )


    sinθ(又はcosθ)から計算すれば速くなりますが、まだ変更していません。

  (4) atan  下記 級数を計算

                       

     |x| > 1 の場合(求める値が45度を越える場合) 1/x として求め、90−θから計算する。

  (5) asin

     sinθ から tanθ を求め、(4)でθを求める。 


     asinθを級数計算で直接求める方法は、値(角度)により収束が悪く誤差が累積して上手く求められません。

  (6) acos

     cosθ から tanθ を求め、(4)でθを求める。

 

  (7) log x (自然対数) 下記 級数を計算

                    

        X = x −1 置きなおして計算する。


  (8) log10  x (常用対数) 

     自然対数に変換してから計算する。

     log x /log(10)

     log x はノーマライズした値。

  (9) exp   下記 級数を計算 

   ........................            


  (10) pow   x の y乗

     @ y が浮動少数の場合

         z=exp(y*log(x))   を計算。

     A yが整数の場合 

        @では精度が少し悪くなる場合があるから y回掛け算する。
        @とは別関数名にしました。

     0の0乗は?

       数学的意味を持たないようですが、コンパイラによって結果が違います。
       H8に移植したらさっぱり動かないので調べたら下記の様になったました。
       (ちなみに元(VB)は、本から引用した多項式を計算する部分。)
       そんなコードが悪いと言われればそれまでですが。

        VB の Ver.6         -----  1.0
        VC++            ----- 1.0
        BC5.5            ----- 1.0
        gcc(H8)           ----- 1.0
        ルネサスレテクノロジH8評価版  ----- 0.0
        lisc86試食版          ----- 0.0

        多数決??で、 1.0 の勝ち
        グラフから見ると1.0が自然な気がします。

   (11) 双曲線関数   

                     

   (12) sqrt   平方根(ルート)

      sqrt(a) の値をニュートンラプソン方(?)で求める

     x=1 を初期値として

     Xn = x −( x * x - a)/(x * 2)

     求めた Xn を x として新しい Xnを 求める。 これを収束するまで繰り返す。

     相対誤差(err = (Xn−x)/x の絶対値)が収束条件(例えば1.0e-9以下)

     を満たしたら終了。