2020/11/28 C言語辞典のゼータ関数を修正した計算マイナス側の計算精度向上の為、マイナス側の計算式追加。
2020/11/22 C言語辞典のゼータ関数を修正した計算の計算精度UPの為の変更

    double -> extended 変更

リーマンゼータ関数

 リーマンゼータ関数のζ(s)とζ(s)-1の計算です。



 C言語辞典のゼータ関数の場合、sの値がマイナス側になると、誤差が大きくなるので、次の計算を使用することにより、ゼータ関数の計算がプラスとなり、sの値がマイナス側でも精度よく計算が出来るようになります。
但し、ガンマ関数の計算が必要となる為、プログラムが少し長くなります。

 次のプログラムはMathematics Source Library C & ASM の  riemann_zeta_function.c をDelphiに変換したものです。
使用されていないルーチンや無駄なルーチンもあるので、他のプログラムに組み込む場合は、後述のプログラムの方が、小さく簡単です。
実行画面は、同じです。

unit main;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, system.Math, Vcl.StdCtrls, Vcl.Buttons,
  Vcl.ExtCtrls, VclTee.TeeGDIPlus, VCLTee.Series, VCLTee.TeEngine,
  VCLTee.TeeProcs, VCLTee.Chart, system.UITypes;

type
  TForm1 = class(TForm)
    Memo1: TMemo;
    BitBtn1: TBitBtn;
    LabeledEdit1: TLabeledEdit;
    Chart1: TChart;
    Series1: TLineSeries;
    Series2: TLineSeries;
    Series3: TPointSeries;
    procedure FormCreate(Sender: TObject);
    procedure BitBtn1Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;
  LDBL_EPSILON : extended;

implementation

{$R *.dfm}

uses dirichlet_eta;

function xRiemann_Zeta_Function(s: extended): extended; forward;
function xRiemann_Zeta_Star_Function(s: extended): extended; forward;

//------------------------------------------------------------------------------
// function Riemann_Zeta_Function(s: double): double;
//
//  Description:
//     The Riemann zeta function is defined as:
//                          zeta(s) = Sum (1/k^s),
//     summed over k = 1,... where s is a complex number with Re(s) > 1,
//     then analytically continued to the rest of the complex plane save for
//     a simple pole at s = 1.
//     This routine calculates the Riemann zeta function for real s != 1.
//     If s = 1, DBL_MAX is returned.
//     If zeta(s) > DBL_MAX, then DBL_MAX is returned and
//     if zeta(s) < -DBL_MAX, then -DBL_MAX is returned. Note that
//     lim zeta(s) = -inf where s->1 from the left and lim zeta(s) = inf
//     where s->1 from the right.
//
//------------------------------------------------------------------------------
function Riemann_Zeta_Function(s: double): double;
var
  zeta: extended;
begin
  if s = 1.0 then begin
    result := MAXDouble;
    exit;
  end;
  zeta := xRiemann_Zeta_Function(s);
  if abs(zeta) < MAXDouble then begin
    result := zeta;
    exit;
  end;
  if zeta >= MAXDouble then result := MAXDouble
  else result := -MAXDouble;
end;

//------------------------------------------------------------------------------
// function xRiemann_Zeta_Function(s: extended): extended
//
//  Description:
//     The Riemann zeta function is defined as:
//                          zeta(s) = Sum (1/k^s),
//     summed over k = 1,... where s is a complex number with Re(s) > 1,
//     then analytically continued to the rest of the complex plane save for
//     a simple pole at s = 1.
//     This routine calculates the Riemann zeta function for real s != 1.
//     If s = 1, LDBL_MAX is returned.
//     lim zeta(s) = -inf where s->1 from the left and lim zeta(s) = inf
//     where s->1 from the right.
//------------------------------------------------------------------------------
function xRiemann_Zeta_Function(s: extended): extended;
begin
  if s = 1.0 then begin
    result := MAXExtended;
    exit;
  end;
  result := xDirichlet_Eta_Function(s) / (1.0 - power(2.0, 1.0 - s));
end;

//------------------------------------------------------------------------------
// function Riemann_Zeta_Star_Function(s: double): double;
//
//  Description:
//     This routine calculates the Riemann zeta star function defined as
//                           zeta*(s) = zeta(s) - 1,
//     where zeta() is the Riemann zeta function for real s != 1.
//------------------------------------------------------------------------------
function Riemann_Zeta_Star_Function(s: double): double;
var
  x: extended;
begin
  x := xRiemann_Zeta_Star_Function(s);
  if abs(x) < MaxDouble then begin
    result := x;
    exit;
  end
  else if  x > 0.0 then  result :=MAXDouble else result := - MAXDouble;
end;

//------------------------------------------------------------------------------
// function xRiemann_Zeta_Star_Function(s : extended): extended;
//
//  Description:
//     This routine calculates the Riemannt zeta star function defined as
//                           zeta*(s) = zeta(s) - 1,
//     where zeta() is the Riemann zeta function for real s != 1.
//------------------------------------------------------------------------------
function xRiemann_Zeta_Star_Function(s: extended): extended;
var
  two_s: extended;
  eta: extended;
  temp: extended;
begin
  two_s := power(2.0, s - 1.0);
  eta := xDirichlet_Eta_Star_Function(s);
  if s = 1.0 then begin
    result := MAXDouble;
    exit;
  end;
  if s < 0.0  then begin
    two_s := 1.0 / two_s;
    result := (eta + two_s) / (1.0 - two_s);
    exit;
  end;
  temp := two_s - 1.0;
  result := (two_s * eta + 1.0) / temp;
end;

//------------------------------------------------------------------------------
// 計算の実行とグラフ作成
//------------------------------------------------------------------------------
procedure TForm1.BitBtn1Click(Sender: TObject);
const
  n = 400;
var
  zeta: double;
  star: double;
  s : double;
  i : integer;
  min, max, dx: double;
begin
  val(LabeledEdit1.Text, s, i);
  if i <> 0 then begin
    MessageDlg('xの値に間違いがあります。', mtInformation,
      [mbOk], 0, mbOk);
    exit;
  end;
  zeta := Riemann_Zeta_Function(s);
  star := Riemann_Zeta_Star_Function(s);
  Memo1.Clear;
  Memo1.Lines.Add('ζ関数');
  // s = 1の時はMaxDoubleになるので∞を表示
  if s <> 1 then begin
    Memo1.Lines.Add('ζ(x)      = ' + floatTostr(zeta));
    Memo1.Lines.Text := Memo1.Lines.Text + 'ζ(x) - 1 = ' + floatTostr(star);
//  Memo1.Lines.Add('ζ(x) - 1 = ' + floatTostr(star));
  end
  else begin
    Memo1.Lines.Add('ζ(x)      = ∞');
    Memo1.Lines.Text := Memo1.Lines.Text + 'ζ(x) - 1 = ∞';
  end;
  Series1.Clear;
  Series2.Clear;
  Series3.Clear;
  // グラフ表示の演算精度はSingle
  if abs(zeta) < MaxSingle then Series3.AddXY(s, zeta);
  min := round(s - 2);
  max := round(s + 3);
  dx := (max - min) / n;
  for i := 0 to n do begin
    s := i * dx + min;
    zeta := Riemann_Zeta_Function(s);
    if abs(zeta) < 30 then
      if s < 1 then Series1.AddXY(s, zeta)
               else Series2.AddXY(s, zeta);
  end;
end;

//-------------------------------------------
// extended の Epsilon 設定
//-------------------------------------------
procedure TForm1.FormCreate(Sender: TObject);
var
  d, m: extended;
begin
  Memo1.Clear;
  LDBL_EPSILON := 1;
  d := 1;
  repeat
    LDBL_EPSILON := LDBL_EPSILON / 2;
    m := d + LDBL_EPSILON;
  until m = d;
  LDBL_EPSILON := LDBL_EPSILON * 2;
end;

end.
unit dirichlet_eta;

interface

  function xDirichlet_Eta_Function(s : extended): extended;
  function xDirichlet_Eta_Star_Function(s: extended): extended;

implementation

uses system.math, Gamma_Function, main;

//function xDirichlet_Eta_Star_Function(s: extended): extended; forward;
function Alternating_Series_Convergence_Acceleration(s: extended): extended;  forward;
function Sum_Reverse_Order(s : extended): extended; forward;
function Reflection_Coefficient(s: extended): extended; forward;

//-----------------------------------------------------------------------
// function Dirichlet_Eta_Function(s: extended): extended;
//
//     このルーチンは、実数のEta関数を計算します
//            eta(s)=(1-2 ^(1-s))zeta(s)、
//     ここで、zeta()はリーマンゼータ関数です。s> 1の場合、
//            eta(s)= Sum(-1)^(k-1)(1 / k ^ s)、
//     ここで、合計は k = 1...eta(1)= ln(2)
//
//   s <1の場合、反射式が使用されることに注意してください
//     s << 0の場合 eta(s)の傾きは、大きさが大きく、摂動が小さい
//  引数は大きな絶対誤差を作成する可能性があります。
//-----------------------------------------------------------------------
function xDirichlet_Eta_Function(s : extended): extended;
begin
  if (s >= 64.0) then begin
    result :=  1.0;
    exit;
  end;
  result := 1.0 + xDirichlet_Eta_Star_Function(s);
end;

//--------------------------------------------------------------------------------
// function xDirichlet_Eta_Star_Function(s: extended): extended;
//    このルーチンは、次のように定義されたDirichlet's eta関数を計算します
//              eta *(s)= eta(s)-1、
//    ここで、eta()はディリクレのイータ関数です。//
//--------------------------------------------------------------------------------
function xDirichlet_Eta_Star_Function(s: extended): extended;
var
  reflection_coefficientd: extended;
begin
  if s >= 0.0 then  begin
    if  s < 18.0 then
      result := Alternating_Series_Convergence_Acceleration(s)
    else
      result := Sum_Reverse_Order(s);
    exit;
  end;

  // Use the reflection formula
  reflection_coefficientd := Reflection_Coefficient(s);
  result := reflection_coefficientd * xDirichlet_Eta_Star_Function(1.0 - s)
          + (reflection_coefficientd - 1.0);
end;

//---------------------------------------------------------------------------
// function Reflection_Coefficient(s: extended): extemded;
//    ディリクレのイータ関数の反射公式は次のとおりです。
//    eta(s)= {[2 *(1-2 ^(1-s))/(1-2 ^ s)] *Gamma(1-s)
//   (2 * pi)^(1-s)* cos((1-s)* pi / 2)} * eta(1-s)
//    ここで、s <0は負の実数です。
//
//    このルーチンは係数を返します
//     [2 *(1-2^(1-s))/(1-2^s)]Gamma(1-s)/(2 * pi)^(1-s)*cos((1-s)* pi/2)
//    ここで、s <0は負の実数です。
//---------------------------------------------------------------------------
function Reflection_Coefficient(s: extended): extended;
var
  one_s: extended;
  k : integer;
  v : extended;
  c : extended;
  x, temp : extended;
begin
  one_s := 1.0 - s;
  k := trunc(one_s / 4.0);
  v := one_s - 4.0 * k;
  c := cos(v * pi / 2);
  if abs(c) < 1.8 * LDBL_EPSILON then begin
    result := 0.0;
    exit;
  end;
  temp := power(2.0, one_s);
  x := (1.0 - temp) / (temp - 2.0);
  x := x + x;
  x := x * c;
  x := x * xGamma_Function(one_s);
  x := x / power(pi, one_s);
  result := x;
end;

//-----------------------------------------------------------------------------
// function Alternating_Series_Convergence_Acceleration(s: extended): extended;
//    このルーチンは、s <= 18のEta関数を計算します。
//    ゆっくりと収束します。
//     Technique:
//     Given an alternating series: Sum (-1)^k a[k] summmed over k = 0,...
//     where a[k] > 0 for all k.  If there exits a positive function w(x)
//     defined on [0,1] such that a[k] = I[0,1] x^k w(x) dx (the integral
//     from 0 to 1 with respect to x of x^k w(x), then
//          Sum (-1)^k a[k] = Sum (-1)^k I[0,1] x^k w(x) dx
//                          = I[0,1] Sum (-1)^k x^k w(x) dx
//                          = I[0,1] w(x) / (1 + x) dx
//
//     Let S = I[0,1] w(x) / (1 + x) dx.
//     Given a polynomial P(x) of degree n such that P(-1) != 0,
//          P(x) = p[0] - p[1] x + p[2] x^2 - ... (-1)^n p[n] x^n,
//     define S[n] = I[0,1] (P(-1) - P(x)) w(x) / (1+x) dx / P(-1).
//     Then   S[n] = S - I[0,1] P(x) w(x) / (1+x) dx / P(-1)
//     so,   |S[n] - S| <= I[0,1] |P(x)| w(x) / (1+x) dx / |P(x)|
//           |S[n] - S| <= (M / |P(-1)|) S, where M = max |P(x)|, x in [0,1].
//
//     After a little algebra,
//               S[n] = (1/P(-1)) Sum Sum p[j] [(-1)^k a[k]],
//     where the first sum is over k = 0,...,n-1 and the second sum is over
//     j = k+1,...,n.
//     Let d[k] = Sum p[j] summed for j = k+1,...,n for  k = n-1, ..., 0, then
//        S[n] = (1/c[0]) Sum d[k] (-1)^k a[k] summed k = 0,...,n-1.
//
//     The choice for P(x) programmed here is (-1)^n * T*[n](x), where T*[n]
//     is the shifted Chebyshev polynomial of the first kind of degree n.
//     With this choice of P(x),
//              P(x) = Sum {( n / (n+j) ) C(n+j,2j) 4^j (-x)^j},
//     where the sum is over j = 0,...,n and C(n+j,2j) = (n+j)!/[(2j)!(n-j)!]
//     and M = 1, P(-1) >= (1/2) (3 + sqrt(8))^n.
//------------------------------------------------------------------------------
function Alternating_Series_Convergence_Acceleration(s: extended): extended;
const
  d: array[0..28] of extended = (
     1.362725501650887306817e+21, 1.362725501650887306816e+21,
     1.362725501650887305248e+21, 1.362725501650886896000e+21,
     1.362725501650844334208e+21, 1.362725501648488235008e+21,
     1.362725501568066715648e+21, 1.362725499718371770368e+21,
     1.362725469310199922688e+21, 1.362725096810094788608e+21,
     1.362721590926752350208e+21, 1.362695647390018306048e+21,
     1.362542007743905005568e+21, 1.361803869444099801088e+21,
     1.358896740140251611136e+21, 1.349437033675348770816e+21,
     1.323863206542645919744e+21, 1.266218975223368122368e+21,
     1.157712186857668739072e+21, 9.872015194258554224640e+20,
     7.640581139674368573440e+20, 5.220333434317674905600e+20,
     3.061506212814840135680e+20, 1.496014168469232680960e+20,
     5.884825485587356057600e+19, 1.781624012587768217600e+19,
     3.882102878793367552000e+18, 5.404319552844595200000e+17,
     3.602879701896396800000e+16);
var
  term: array[0..27] of extended;
  sum: extended;
  k: integer;
begin
  k := 0;
  while k <= 27 do  begin
    term[k] := d[k + 1] * power(k + 2,-s);
    inc(k);
    term[k] := -d[k + 1] * power(k + 2,-s);
    inc(k)
  end;
  sum := term[27];
  for k := 26 downto 0 do sum := sum + term[k];
  sum := sum / d[0];

  result := -sum;
end;

//-------------------------------------------------------------------------
// long double Sum_Reverse_Order(long double s)//
//
//  このルーチンは、s> = 18のEta関数を計算します(power()への呼び出しは28未満)
//         eta(s)= Sum(-1)^(k-1)(1 / k ^ s)、
//   ここで、合計はk = 1、...で合計されます
//
//     Since the series is alternating, the absolute error is less than the
//     absolute value of the first neglected term.  The number of terms which
//     are summed is determined by calculating successive lower and upper
//     bounds until the two bounds are equal (within truncation errors).
//     The final result is then summed starting with the last term and
//     terminating with the first term, (this is slightly more accurate).
//--------------------------------------------------------------------------
function Sum_Reverse_Order(s : extended): extended;
var
  term: array[0..29] of extended;
  lower_bound: extended;
  upper_bound: extended;
  sum: extended;
  k: integer;
begin
  lower_bound := -power(2.0, -s);
  term[0] := lower_bound;
  term[1] := power(3.0 ,-s);
  upper_bound := term[1] + lower_bound;
  if lower_bound = upper_bound then begin
    result := upper_bound;
    exit;
  end;
  k := 4;
  while k <= 31 do  begin
    term[k-2] := -power(k, -s);
    lower_bound := upper_bound + term[k - 2];
    if lower_bound = upper_bound then break;
    inc(k);
    term[k - 2] := power(k, -s);
    upper_bound := lower_bound + term[ k- 2];
    if lower_bound = upper_bound then break;
    inc(k);
  end;
  k := k - 2;
  sum := term[k];
  for k := k - 1 downto 0 do  sum := sum + term[k];
  result := sum;
end;

end.
unit Gamma_Function;

interface
  function xGamma_Function(x: extended): extended;

implementation

uses system.math;

const
  LONG_MAX = 2147483647;
  max_long_double_arg: extended = 1755.5;
  g =  9.65657815377331589457187;
  e =  2.71828182845904523536028747;
  exp_g_o_sqrt_2pi = 6.23316569877722552586386e+3;
  a: array[0..8] of extended = (
                                +1.14400529453851095667309e+4,
                                -3.23988020152318335053598e+4,
                                +3.50514523505571666566083e+4,
                                -1.81641309541260702610647e+4,
                                +4.63232990536666818409138e+3,
                                -5.36976777703356780555748e+2,
                                +2.28754473395181007645155e+1,
                                -2.17925748738865115560082e-1,
                                +1.08314836272589368860689e-4
                               );

function xGamma(x: extended): extended; forward;

//=============================================================================
//
// この関数はLanczosの式を使用して実際のGamma(x)を計算します。
// xの範囲は -(max_long_double_arg-1) < x < max_long_double_arg。
// ガンマ関数は複素平面で有理型であり、正でない整数の値
// xaの正の整数または半分の正の整数をテストすると、
// 最大絶対相対誤差は約3.5e-16です。
//
// x > max_long_double_argの場合、lnGamma(x)を使用する必要があります。
// x < 0 の場合、ln(Gamma(x)) は複素数になる可能性があることに注意してください。
//
// 戻り値
//  xが正で、max_long_double_argより小さい場合、Gamma(x)
//  が返され、x > max_long_double_argの場合、maxextendedが返されます。
//  xが正でない整数の場合、maxextendedが
//  返されます(Gamma(x)は値の両側で符号を変更することに注意してください)。
//  xが非正の非整数の場合でx>-(max_long_double_arg + 1)の場合
//  Gamma(x)が返されます。それ以外の場合は0.0が返されます
//
//=============================================================================
function xGamma_Function(x: extended): extended;
var
  sin_x: extended;
  rg: extended;
  ix: int64;
begin
  if x > 0 then
    if x <= max_long_double_arg then begin
      result := xGamma(x);
      exit;
    end
    else begin
      result := maxextended;
      exit;
    end;
  if x > -LONG_MAX then begin
    ix := round(x);
    if x = ix then begin
      result := maxextended;
      exit;
    end;
  end;
  sin_x := sin(pi * x);
  if sin_x = 0 then begin
    result := maxextended;
    exit;
  end;
  if x < - max_long_double_arg - 1 then begin
    result := 0;
    exit;
  end;
  rg := xGamma(1 - x) * sin_x / pi;
  if rg <> 0 then result := 1 / rg
             else result := maxextended;
end;

//=============================================================================
//
// この関数は倍数公式を使用してGamma(two_x)を返します。
//
//=============================================================================
function Duplication_Formula(two_x: extended): extended;
var
  x: extended;
  g: extended;
  n: integer;
begin
  x := 0.5 * two_x;
  n := round(two_x) - 1;
  g := power(2.0, two_x - 1.0 - n);
  g := g * power(2, n);
  g := g / sqrt(pi);
  g := g * xGamma_Function(x);
  g := g * xGamma_Function(x + 0.5);
  result := g;
end;

//=============================================================================
//
// この関数はLanczosの式を使用して実際のGamma(x)を計算します。
// x、ここで0<x<=900。900<x<1755.5の場合、倍数公式を使用します。
// 関数power()。結果の相対誤差は約10^-16です。x = 0付近を除きます。
// x>1755.5の場合、lnGamma(x)を計算する必要があります。
// xが正で1755.5未満の場合、Gamma(x)が返され、
// x>1755.5の場合、maxextendedが返されます。
//
//=============================================================================
function xGamma(x: extended): extended;
var
  xx: extended;
  temp: extended;
  n, i: integer;
  xx2 : extended;
begin
  if x < 1 then xx := x + 1 else xx := x;
  n := sizeof(a) div sizeof(extended);
  if x > max_long_double_arg then begin
    result := maxextended;
    exit;
  end;
  if x > 900 then begin
    result := Duplication_Formula(x);
    exit;
  end;
  temp := 0;
  for i := n - 1 downto 0 do temp := temp + a[i] / (xx + i);
  temp := temp + 1;
  xx2 := (xx - 0.5) / 2;
  temp := temp * (power((g + xx - 0.5) / e, xx2) / exp_g_o_sqrt_2pi );
  temp := temp * power((g + xx - 0.5) / e, xx2);      // X64 オーバーフロー対策
  if x < 1 then result := temp / x
           else result := temp;
end;


end.

 次のプログラムは、C言語辞典にあるRiemannのゼータ関数を修正したものです。
xの値が-5より小さくなると、誤差が大きくなっていきます。
2020/11/28 C言語辞典のゼータ関数を修正した計算マイナス側の計算精度向上の為、マイナス側の計算式追加。
2020/11/22 計算精度UPの為の変更

    double -> extended 変更   x がマイナスの時の精度向上

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, VclTee.TeeGDIPlus,
  VCLTee.Series, VCLTee.TeEngine, VCLTee.TeeProcs, VCLTee.Chart;

type
  TForm1 = class(TForm)
    Memo1: TMemo;
    BitBtn1: TBitBtn;
    LabeledEdit1: TLabeledEdit;
    Chart1: TChart;
    Series1: TLineSeries;
    Series2: TPointSeries;
    procedure FormCreate(Sender: TObject);
    procedure BitBtn1Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses system.Math;

var
  GrphF: boolean;

function Gamma(x: Extended): Extended;  // ガンマ関数
const
//ベルヌーイ数B(2)、B(4)、B(6)、...、B(16)
  B : array[1..8] of Extended = ( 1.0 / 6,           // B(2)
                                  -1.0 / 30,
                                   1.0 / 42,
                                  -1.0 / 30,
                                   5.0 / 66,
                                -691.0 / 2730,
                                   7.0 / 6,
                               -3617.0 / 510);     // B(16)

  m: integer = sizeof(B) div sizeof(Extended);
var
  i : integer;
  sum : Extended;
  xx, v  : Extended;
  xj  : Extended;
  lng : Extended;
  ln_sqrt_2pi: Extended;
begin
  ln_sqrt_2pi := ln(sqrt(2 * pi));                    // = ln(2 * pi) / 2;
  sum := 0;
  v := 1;
  while x < m do begin
    v := v * x;
    x := x + 1;
  end;
  xx := x * x;
  xj := x;
  lng := ln_sqrt_2pi - x + (x - 0.5) * ln(x) - ln(v);
  for i := 1 to  m do begin
    sum := sum + B[i] / (i * 2 * (2 * i - 1)) / xj;
    xj := xj * xx;
  end;
  result := exp(sum + lng);
end;

function Riemann_Zeta_Function(x: Extended): Extended;
const
  coef: array[0..19] of Extended = (
  	 8.333333333333333333333333333e-2,  //  1/12
  	-1.388888888888888888888888889e-3,  // -1/720
  	 3.306878306878306878306878307e-5,  //  1/30240
  	-8.267195767195767195767195767e-7,  // -1/1209600
  	 2.087675698786809897921009032e-8,  //  1/47900160
  	-5.284190138687493184847682202e-10,
  	 1.338253653068467883282698098e-11,
  	-3.389680296322582866830195391e-13,
  	 8.586062056277844564135905450e-15,
  	-2.174868698558061873041516424e-16,
  	 5.509002828360229515202652609e-18,
  	-1.395446468581252334070768626e-19,
  	 3.534707039629467471693229977e-21,
  	-8.953517427037546850402611251e-23,
  	 2.267952452337683060310950058e-24,
  	-5.744790668872202445263829503e-26,
  	 1.455172475614864901866244572e-27,
  	-3.685994940665310178130050728e-29,
  	 9.336734257095044668660153106e-31,
  	-2.365022415700629886484029550e-32
    );
var
  i, N : integer;
  powNx, w, z, zprev: Extended;
begin
  if x = 1 then begin
    result := infinity;
    exit;
  end;
  z := 1;
  zprev := z;
  N := 8;
  for i := 2 to N - 1 do begin
    zprev := z;
    z := z + power(i, -x);
    if z = zprev then begin
      result :=  z;
      exit;
    end;
  end;
  powNx := power(N, x);
  w := x / (N * powNx);
  z := z + 0.5 / powNx + N / ((x - 1) * powNx) + coef[0] * w;
  i := 1;
  while  (i < 20) and (z <> zprev) do begin
    w := w * (x + 2 * i - 1) * (x + 2 * i) / (N * N);
    zprev := z;
    z := z + coef[i] * w;
    inc(i);
  end;
  result := z;
end;

function RiemannFunction(s: Extended): Extended;
var
  term : Extended;
  ints : integer;
  def : Extended;
begin
  ints := trunc(s);
  def := s - ints;
  if (s <= -2) and (def = 0) and (ints mod 2 = 0) then
    result := 0
  else
  if s < -1 then begin
    term := power(2, s) * power(pi, s - 1) * sin(pi * s / 2);
    result := term * Riemann_Zeta_Function(1 - s) * Gamma(1 - s);
  end
  else
    result := Riemann_Zeta_Function(s);
end;

procedure TForm1.BitBtn1Click(Sender: TObject);
const
  n = 400;
var
  zeta, s, star: Extended;
  ch, i : integer;
  min, max, dx: Extended;
  gyi : Extended;
begin
  val(labeledEdit1.Text, s, ch);
  if ch <> 0 then begin
    application.MessageBox('入力値に間違いがあります','注意',0);
    exit;
  end;
  memo1.Clear;
  GrphF := False;
  zeta := riemannFunction(s);
  star := zeta - 1;
  if s <> 1 then begin
    Memo1.Lines.Add('ζ(x)      = ' + floatTostr(zeta));
    Memo1.Lines.Text := Memo1.Lines.Text + 'ζ(x) - 1 = ' + floatTostr(star);
  end
  else begin
    Memo1.Lines.Add('ζ(x)      = ∞');
    Memo1.Lines.Text := Memo1.Lines.Text + 'ζ(x) - 1 = ∞';
  end;
  Series1.Clear;
  Series2.Clear;
  application.ProcessMessages;
  gyi := 30;
  if s < -3 then gyi := MaxDouble / 2;
  if abs(zeta) < gyi then Series2.AddXY(s, zeta);
  GrphF := True;
  min := round(s - 2);
  max := round(s + 3);
  dx := (max - min) / n;
  for i := 0 to n do begin
    s := i * dx + min;
    zeta := riemannFunction(s);
    if abs(zeta) <= gyi then
      Series1.AddXY(s, zeta,'', $FF8000)
    else begin
      if zeta > gyi then zeta := gyi;
      if zeta < -gyi then zeta := -gyi;
      if zeta > 0 then
        Series1.AddXY(s, gyi,'', clbtnface)
      else
        Series1.AddXY(s, -gyi,'', clbtnface);
    end;
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  memo1.Clear;
end;

end.

 
  download Riemann_zeta_function.zip

各種プログラム計算例に戻る