逆Pi関数


17

Pi関数は、実数(または複素数)の階乗の拡張です。整数nの場合Π(n)= n!、しかし実数の定義を得るには、積分を使用して定義します:

Pi(z)= 0から無限大までの整数t e ^ -tt ^ z dt

この課題では、Π関数を反転します。

実数を考えるとZ≥1 、正見つけます XはそのようなことをΠ(x)= Z。回答は、少なくとも5桁の10進数で正確でなければなりません。


例:

120 -> 5.0000
10 -> 3.39008
3.14 -> 2.44815
2017 -> 6.53847
1.5 -> 1.66277

4
より多くの人がガンマ(Γ)関数を使用することに注意してください。Π(x)=Γ(x + 1)。しかし、IMOΓはシフトされた憎悪であり、Πは階乗の真の拡張です。
orlp

1
Wellp、その級数展開が私を怖がらせるのに十分です... i.imgur.com/ttgzDSJ.gif
マジックタコ壺

1
たとえば、すべての例には他のソリューションもあり120 -> -0.991706ます。これは、xが右から-1になるとΠ(x)が無限大になるためです。おそらく、x> 0であることを主張するつもりです。
グレッグマーティン

@GregMartinも追加されました。
orlp

1
それは不自然に思えますが、シフトされたバージョンを好むいくつかの理由があります。たとえば、MathOverflowでのこの回答およびそのページの他の回答を参照してください。
ルスラン

回答:


8

Mathematica、17 15 27バイト

FindInstance[#==x!&&x>0,x]&

出力はのよう{{x -> n}}になります。ここnで、ソリューションは許可されない可能性があります。


7

Pyth、4バイト

.I.!

数値を入力して結果を出力するプログラム。

テストスイート

使い方

.I.!    Program. Input: Q
.I.!GQ  Implicit variable fill
.I      Find x such that:
  .!G    gamma(x+1)
     Q   == Q
        Implicitly print

5

MATL、13バイト

1`1e-5+tQYgG<

これは、で1e-5始まるステップで線形検索を使用します1。そのため、非常に遅く、オンラインコンパイラでタイムアウトになります。

それをテストするために、次のリンクは1e-5精度要件をに置き換えます1e-2オンラインでお試しください!

説明

1        % Push 1 (initial value)
`        % Do...while
  1e-5   %   Push 1e-5
  +      %   Add
  t      %   Duplicate
  QYg    %   Pi function (increase by 1, apply gamma function)
  G<     %   Is it less than the input? If so: next iteration
         % End (implicit)
         % Display (implicit)

3

GeoGebra、25バイト

NSolve[Gamma(x+1)=A1,x=1]

CAS入力に入力され、スプレッドシートセルに数値が入力されることを想定していますA1。フォームの1要素配列を返します{x = <result>}

実行のgifは次のとおりです。

プログラムの実行

使い方

N数値的にSolveは、次の方程式:Gamma(x+1)=A1開始値x=1


正の数を返すことが保証されていますか?1.5で動作しますか?
パベル

@Pavelで動作することを確認できます1.5。GeoGebraが数値解法に使用するアルゴリズムを見つけることはできませんでしたが、の初期値は、x=1試したすべての値に対して純粋に肯定的な答えを与えました。
-TheBikingViking

2

MATLAB、59バイト

@(x)fminsearch(@(t)(gamma(t+1)-x)^2,1,optimset('TolF',eps))

これは、で始まる1非常に小さな許容差(で与えられるeps)でPi関数とその入力の間の2乗差の最小化を求める匿名関数で、目的の精度を実現します。

テストケース(Matlab R2015bで実行):

>> @(x)fminsearch(@(t)(gamma(t+1)-x)^2,1,optimset('TolF',eps))
ans = 
    @(x)fminsearch(@(t)(gamma(t+1)-x)^2,1,optimset('TolF',eps))
>> f = ans; format long; f(120), f(10), f(3.14), f(2017)
ans =
   5.000000000000008
ans =
   3.390077650547032
ans =
   2.448151165246967
ans =
   6.538472664321318

Octave でオンライン試すこともできますが、残念なことに結果の一部には必要な精度がありません。


2

J、 86 33バイト

((]-(-~^.@!)%[:^.@!D.1])^:_>:)@^.

オーバーフローを回避するために、ログPiでニュートンの方法を使用します。

これは、スターリング近似を使用して対数ガンマを計算する以前のバージョンです。パフォーマンスを犠牲にして精度を高めるために、ステップサイズ(1e3)とlogガンマの項の数(3)を増やすことができます。

3 :'(-(k-~g)%%&1e3(g=:((%~12 _360 1260 p.&:%*:)+-+^~-&^.%:@%&2p1)@>:)D:1])^:_>:k=:^.y'

その場で係数項を計算する別のバージョン

3 :'(-((-^.y)+g)%%&1e3(g=:((%~(((%1-^@-)t:%]*<:)+:>:i.3)p.%@*:)+(*^.)-]+-:@^.@%&2p1)@>:)D:1])^:_>:^.y'

オンラインでお試しください!そして、用語が収束するのを見ます。

説明

((]-(-~^.@!)%[:^.@!D.1])^:_>:)@^.  Input: float y
(                            )@^.  Operate on log(y)
                           >:        Increment, the initial guess is log(y)+1
 (                     )^:_          Repeat until convergence starting with x = log(y)+1
                      ]                Get x
               ^.@!                    The log Pi verb
             [:    D.1                 Approximate its first derivative at x
       ^.@!                            Apply log Pi to x
     -~                                Subtract log(y) from it
            %                          Divide it by the derivative
  ]-                                   Subtract it from x and use as next value of x

2

Mathematica、21バイト

FindRoot[#-x!,{x,1}]&

FindRoot 初期値がある場合、Newtonのメソッドを内部的に適用します。

以下の2つの方法は、Newtonの方法を直接適用します。

FixedPoint 45バイトを使用する代替

FixedPoint[#-(#!-y)/Gamma'[#+1]&,Log[y=#]+1]&

Mathematicaは微分を近似する代わりに直接計算できるため、これを解決するためのニュートンの方法のより正確な実装。

繰り返し置換するルールを使用すると短くなりますが、実行できる反復回数には制限がありますが、ヒットFixedPointしない可能性があります(65536)。

代替の使用ルール、38バイト

Log[y=#]+1//.x_->x-(x!-y)/Gamma'[x+1]&

画像


1

ゼリー、34バイト

Ḋ!Æl_®
ȷİ‘×;µ!ÆlI÷I÷@Ç_@ḊḢ
Æl©‘ÇÐĿ

オンラインでお試しください!または、収束する中間値を表示します

逆数計算するニュートン法及び誘導体近似(割線法)のJの組み合わせの実装Πnは)のます。

log(Πnオーバーフローを回避するために、代わりに))。

最初の推測x 0 = y +1で始まります。ここで、y = log(Πn))です。次に、x n +1 = x n-(log(Πx n))- y)/(log((Π(1.001 * x n))-log(Πx n)))/ を使用して収束するまで反復します(0.001 * x n))。


3
入力でエラーが発生しました1.5
ルイスメンドー

@LuisMendoうわー、それは良いキャッチです!これは、中間値の1つが〜65807であるために発生します。これは、ガンマが適用された後の巨大な値であり、Pythonがオーバーフローします。同じ計算に依存しているため、Jでも同じことが起こります。
マイル


1

Mathematica、26バイト

さらに別のMathematicaソリューション!

方程式の解法は、常に最小化問題に変えることができます。

NArgMin[{(#-x!)^2,x>0},x]&

方程式の左右の差を最小化する引数を見つけます。

NMinimizeの代わりにNArgMinを使用すると、通常の冗長なルールベースの出力ではなく、出力が目的の結果になるように強制されます(そして、バイトを節約します!)


0

C、libm、111

更新 -入力1.5で修正されました。

f(double *z){double u=2**z,l=0,g=u,p=0;for(;log(fabs(g-p))>-14;)p=g,g=(u+l)/2,u=tgamma(g+1)>*z?g:(l=g,u);*z=g;}

gamma(x+1)は、問題の範囲にわたって単調に増加する関数であり、shisは連続する値の差が小さくなるまで単なるバイナリ検索です。開始下限はで0あり、開始上限は2*xです。

入力と出力は、関数に渡されるdoubleへのポインターを介して行われます。

これはもっと深くゴルフできると確信しています-特に4つのローカルダブルが必要だとは思いませんが、これまでのところこれを減らす簡単な方法は見当たりません。

オンラインで試す -ビルド(libmとリンク)およびbashスクリプトで実行します。

軽度の制限なし:

f(double *z){
    double u=2**z,l=0,g=u,p=0;
    for(;log(fabs(g-p))>-14;){
        p=g;
        g=(u+l)/2;
        u=tgamma(g+1)>*z?g:(l=g,u);*z=g;
    }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.