三角関数、双曲線関数、自然対数、指数関数

 各関数をマクローリン展開、あるいはテイラー展開で計算するプログラムです。
各展開については、インターネットで検索してください。

 三角関数は、分かり易くするため、角度入力です。
tanの計算は、ベルヌーイ数を必要とするので、ここでの計算は、sin/cosとしています。
 双曲線関数は、大きな値をいれると、オーバーフローが発生します。



プログラム

unit Main;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.Buttons, Vcl.ExtCtrls;

type
  TForm1 = class(TForm)
    LabeledEdit1: TLabeledEdit;
    BitBtn1: TBitBtn;
    Memo1: TMemo;
    LabeledEdit2: TLabeledEdit;
    BitBtn2: TBitBtn;
    LabeledEdit3: TLabeledEdit;
    BitBtn3: TBitBtn;
    LabeledEdit4: TLabeledEdit;
    BitBtn4: TBitBtn;
    procedure BitBtn1Click(Sender: TObject);
    procedure BitBtn2Click(Sender: TObject);
    procedure BitBtn3Click(Sender: TObject);
    procedure BitBtn4Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

// マクローリン展開(Maclaurin expansion) による 自然関数 計算
// e^x
function exponential(x: double): double;
var
  i : integer;
  d, bu, u: double;
begin
  d := x;
  i := 2;
  u := x;
  repeat
    bu := u;
    d := d * x / i;
    u := u + d;
    inc(i);
  until (bu = u) or (i > 500);
  result := 1 + u;
  Form1.memo1.Lines.Append('    Loop= ' + inttostr(i - 2));
end;


// ln(x)
// https://qiita.com/MilkySaitou/items/614fcbb110cae5b9f797
var Loop : integer;       // 再帰呼び出しがあるのでループ数外側に宣言

function logarithm(x: double): double;
var
  i, k, j : integer;
  a, t, bt: double;
  h       : double;
begin
  if x <= 0 then begin
    result := 0;
    exit;
  end;
  a := 1;
  t := 0;
  if x >= 2 then begin
    t := - logarithm(1 / x);
  end
  else begin
    h := 1 / 2;                           // h = 0.5  0.5の誤差をなくすため
    if x < h then begin
      t := logarithm(h) + logarithm(x / h);
    end
    else begin
      i := 1;
      k := i;
      j := 1;
      repeat
        bt := t;
        a := a * (x - 1);
        t := t + a / k;
        inc(i);
        j := -j;
        k := i * j;
      until (bt = t) or (i > 1000);
      Loop := Loop + (i - 1);           // ループ数合計
//      Form1.memo1.Lines.Append('    Loop= ' + inttostr(i - 1));
    end;
  end;
  result := t;
end;

// ln(x) = 2 artanh((x-1)/(x+1))
// artanh(x)はマクローリン展開
function logarithm_A(x: double):double;
var
  i, k : integer;
  v, t, e, vb: double;
begin
  e := (x - 1) / (x + 1);
  t := e;
  v := e;
  i := 3;
  k := 0;
  repeat
    vb := v;
    t := t * e * e;
    v := v + t / i;
    inc(i, 2);
    inc(k);
  until (vb = v) or (k > 100000);
  Form1.memo1.Lines.Append('    Loop= ' + inttostr(k));
  result := v * 2;
end;

// マクローリン展開(Maclaurin expansion) による 三角関数 双曲線関数 計算
// sin
// x (rad)
function sin_program(x: double): double;
var
  v, d, sq, u : double;
  i, k        : integer;
begin
  d := x;
  sq := x * x;
  u := d;
  i := 1;
  repeat
    v := u;
    k := i * 2;
    d := - d * sq / k / (k + 1);
    u := v + d;
    inc(i)
  until (v = u) or (i > 100);
  result := v;
  Form1.memo1.Lines.Append('Loop= ' + inttostr(i - 1));
end;

// cos
// x (rad)
function cos_program(x: double): double;
var
  d, s, e : double;
  i, k    : integer;
begin
  e := 1;
  s := 1;
  i := 1;
  k := 0;
  repeat
    d := s;
    e := -e * x * x / (i * (i + 1));
    s := s + e;
    i := i + 2;
    inc(k);
  until (s = d) or (i > 100);
  result := s;
  Form1.memo1.Lines.Append('Loop= ' + inttostr(k));
end;

// sinh
// x
function sinh_program(x: double): double;
var
  v, d, sq, u : double;
  i, k        : integer;
begin
  d := x;
  sq := x * x;
  u := d;
  i := 1;
  repeat
    v := u;
    k := i * 2;
    d := d * sq / k / (k + 1);
    u := v + d;
    inc(i)
  until (v = u) or (i > 100);
  result := v;
  Form1.memo1.Lines.Append('Loop= ' + inttostr(i - 1));
end;

// cosh
// x
function cosh_program(x: double): double;
var
  d, s, e : double;
  i, k    : integer;
begin
  e := 1;
  s := 1;
  i := 1;
  k := 0;
  repeat
    d := s;
    e := e * x * x / (i * (i + 1));
    s := s + e;
    i := i + 2;
    inc(k);
  until (s = d) or (i > 100);
  result := s;
  Form1.memo1.Lines.Append('Loop= ' + inttostr(k));
end;

// sin cos tan 計算
// 0°90°180° に関しては別計算にしたほうが良いでしょう。
procedure TForm1.BitBtn1Click(Sender: TObject);
var
  x, deg, adeg, s, c, t : double;
  chc      : integer;
begin
  val(Labelededit1.Text, deg, chc);
  if chc <> 0 then begin
    application.MessageBox('入力値に誤りがあります。','注意',0);
    exit;
  end;
  memo1.Clear;
  adeg := abs(deg);                           // |deg|
  repeat                                      // -180 ~180°に設定
    if adeg > 180 then adeg := adeg - 360;
  until adeg <= 180;
  if deg < 0 then adeg := -adeg;              // 符号再現
  memo1.Lines.Append('x(rad) = ' + floatTostr(deg) + ' / 180 * π');
  x := adeg / 180 * pi;
  memo1.Lines.Append('        x= ' + floattostr(x));
  memo1.Lines.Append(' マクローリン展開');
  s := sin_program(x);
  memo1.Lines.Append('       sin(x)=   ' + floattostr(s));
  c := cos_program(x);
  memo1.Lines.Append('       cos(x)=  ' + floattostr(c));
  memo1.Lines.Append('tan = sin / cos');
  t := s / c;
  memo1.Lines.Append('       tan(x)=  ' + floattostr(t));
end;

// e^x 計算
procedure TForm1.BitBtn2Click(Sender: TObject);
var
  chc: integer;
  x, ex, exf : double;
begin
  val(Labelededit2.Text, x, chc);
  if chc <> 0 then begin
    application.MessageBox('入力値Xに誤りがあります。','注意',0);
    exit;
  end;
  memo1.Clear;
  memo1.Lines.Append(' マクローリン展開');
  ex := exponential(x);
  memo1.Lines.Append('    e^x= ' + floattostr(ex));
  exf := exp(x);
  memo1.Lines.Append(' Math.exp(x)');
  memo1.Lines.Append('        e^x= ' + floattostr(exf));
end;

// ln(x)
procedure TForm1.BitBtn3Click(Sender: TObject);
var
  chc: integer;
  x, lnx, lnxf : double;
begin
  val(Labelededit3.Text, x, chc);
  if chc <> 0 then begin
    application.MessageBox('入力値Xに誤りがあります。','注意',0);
    exit;
  end;
  memo1.Clear;
  if x <= 0 then
    memo1.Lines.Append(' X <= 0 は無効な値です。');
  memo1.Lines.Append(' マクローリン展開');
  loop := 0;
  lnx := logarithm(x);
  Form1.memo1.Lines.Append('    Loop= ' + inttostr(loop));
  memo1.Lines.Append('    ln(x)= ' + floattostr(lnx));
  memo1.Lines.Append(' ln(x) = 2 * arctanh((x-1)/(x+1))');
  lnx := logarithm_A(x);
  memo1.Lines.Append('    ln(x)= ' + floattostr(lnx));
  lnxf := 0;
  if x > 0 then lnxf := ln(x);
  memo1.Lines.Append(' Math.ln(x)');
  memo1.Lines.Append('        ln(x)= ' + floattostr(lnxf));
end;

// sinh, cosh, tanh
procedure TForm1.BitBtn4Click(Sender: TObject);
var
  x : double;
  sh, ch, th : double;
  chc      : integer;
begin
  val(Labelededit4.Text, x, chc);
  if chc <> 0 then begin
    application.MessageBox('入力値に誤りがあります。','注意',0);
    exit;
  end;
  memo1.Clear;
  memo1.Lines.Append(' マクローリン展開');
  sh := sinh_program(x);
  memo1.Lines.Append('       sinh(x)= ' + floattostr(sh));
  ch := cosh_program(x);
  memo1.Lines.Append('       cosh(x)= ' + floattostr(ch));
  memo1.Lines.Append('tanh = sinh / cosh');
  th := sh / ch;
  memo1.Lines.Append('       tanh(x)= ' + floattostr(th));
end;

end.


download trigonometric_function.zip

  三角関数、逆三角関数、その他関数 に戻る