Inverse Pi-Funktion

17

Die Pi-Funktion ist eine Erweiterung der Fakultät über die Realzahlen (oder sogar komplexe Zahlen). Für ganze Zahlen n ist Π (n) = n! , aber um eine Definition über die Realwerte zu erhalten, definieren wir sie mit einem Integral:

Pi (z) = Integral t von 0 bis unendlich e ^ -tt ^ z dt

In dieser Challenge werden wir die Π- Funktion invertieren .

Wenn eine reelle Zahl z ≥ 1 gegeben ist , finde positives x, so dass Π (x) = z ist . Ihre Antwort muss mindestens 5 Dezimalstellen lang sein.


Beispiele:

120 -> 5.0000
10 -> 3.39008
3.14 -> 2.44815
2017 -> 6.53847
1.5 -> 1.66277
orlp
quelle
4
Beachten Sie, dass Menschen die Gamma (Γ) -Funktion häufiger verwenden. Π (x) = Γ (x + 1) . Aber IMO Γ ist ein verschobener Gräuel, und Π ist die wahre Erweiterung der Fakultät.
Orlp
1
Nun, diese Serienerweiterung ist genug, um mich zu erschrecken ... i.imgur.com/ttgzDSJ.gif
Magic Octopus Urn
1
Alle von Ihnen angegebenen Beispiele haben beispielsweise auch andere Lösungen 120 -> -0.991706. Dies liegt daran, dass Π (x) nach unendlich geht, während x von rechts nach -1 geht. Vielleicht wollen Sie auch darauf bestehen, dass x> 0 ist.
Greg Martin
@ GregMartin Hinzugefügt auch.
Orlp
1
Es gibt einige Gründe, die verschobene Version zu bevorzugen, obwohl sie unnatürlich erscheint. Siehe zB diese Antwort auf MathOverflow sowie andere auf dieser Seite.
Ruslan

Antworten:

8

Mathematica, 17 15 27 Bytes

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

Die Ausgabe sieht aus wie {{x -> n}}, wo nist die Lösung, die möglicherweise nicht zulässig ist.

Pavel
quelle
7

Pyth, 4 Bytes

.I.!

Ein Programm, das eine Zahl eingibt und das Ergebnis druckt.

Testsuite

Wie es funktioniert

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

MATL , 13 Bytes

1`1e-5+tQYgG<

Dies verwendet die lineare Suche in Schritten von 1e-5beginnend bei 1. Es ist also furchtbar langsam und läuft im Online-Compiler aus.

Zum Testen ersetzt der folgende Link die 1e-5Genauigkeitsanforderung durch 1e-2. Probieren Sie es online!

Erläuterung

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)
Luis Mendo
quelle
3

GeoGebra , 25 Bytes

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

Wird in die CAS-Eingabe eingegeben und erwartet die Eingabe einer Zahl in der Tabellenzelle A1. Gibt ein Array mit einem Element des Formulars zurück {x = <result>}.

Hier ist ein GIF der Ausführung:

Ausführung des Programms

Wie es funktioniert

Numerisch Solvefolgende Gleichung :, Gamma(x+1)=A1mit Startwert x=1.

TheBikingViking
quelle
Gibt es garantiert eine positive Zahl zurück und funktioniert es für 1.5, das mehrere Antworten gebrochen hat?
Pavel
@Pavel Ich kann bestätigen, dass es funktioniert 1.5. Ich konnte nicht herausfinden, welchen Algorithmus GeoGebra zum numerischen Lösen verwendet, aber der Anfangswert von x=1hat für jeden Wert, den ich ausprobiert habe, rein positive Antworten gegeben.
TheBikingViking
2

MATLAB, 59 Bytes

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

Hierbei handelt es sich um eine anonyme Funktion, mit der der Minimierer der Quadratdifferenz zwischen der Pi-Funktion und ihrer Eingabe beginnend bei 1mit einer sehr kleinen Toleranz (gegeben durch eps) ermittelt wird, um die gewünschte Genauigkeit zu erzielen.

Testfälle (laufen auf 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

Sie könnten es online in Octave versuchen , aber leider fehlt einigen Ergebnissen die erforderliche Präzision.

Luis Mendo
quelle
2

J 86 33 Bytes

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

Verwendet die Newton-Methode mit log Pi, um einen Überlauf zu vermeiden.

Dies ist die vorherige Version, die das Log-Gamma nach Stirlings Näherung berechnet. Die Schrittgröße (1e3) und die Anzahl der Terme in log Gamma (3) kann erhöht werden, um möglicherweise eine höhere Genauigkeit zu erzielen, und dies zu Lasten der Leistung.

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

Eine andere Version, die die Koeffiziententerme im laufenden Betrieb berechnet

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

Probieren Sie es online! und die Begriffe konvergieren zu sehen .

Erläuterung

((]-(-~^.@!)%[:^.@!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
Meilen
quelle
2

Mathematica, 21 Bytes

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

FindRoot Wendet die Newton-Methode intern an, wenn ein Anfangswert vorliegt.

Die beiden folgenden Methoden wenden die Newton-Methode direkt an.

Alternative mit FixedPoint 45 Bytes

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

Eine genauere Implementierung von Newtons Methode zur Lösung dieses Problems, da Mathematica die Ableitung direkt berechnen kann, anstatt sie zu approximieren.

Die Verwendung von Regeln zum wiederholten Ersetzen wäre kürzer, aber es gibt ein Limit (65536) für die Anzahl der Iterationen, die getroffen werden können, während FixedPointes kein Limit gibt.

Alternative mit Regeln, 38 Bytes

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

Bild

Meilen
quelle
1

Gelee , 34 Bytes

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

Probieren Sie es online! oder Zeigen Sie die konvergierenden Zwischenwerte an .

Eine Implementierung von Js Kombination aus Newtons Methode und derivativer Approximation (Sekantenmethode) zur Berechnung der Inversen von Π ( n ) .

Es wird nach der Umkehrung von log aufgelöst ( stattdessen Π ( n )) aufgelöst, um einen Überlauf zu vermeiden.

Es beginnt mit einer anfänglichen Schätzung x 0 = y +1, wobei y = log ( Π ( n )). Dann iteriert es bis zur Konvergenz mit x n + 1 = x n - (log ( Π ( x n )) - y ) / (log (( Π (1.001 * x n )) - log ( Π ( x n )) / (0,001 * x n )).

Meilen
quelle
3
Ich erhalte einen Fehler bei der Eingabe1.5
Luis Mendo
@ LuisMendo Wow, das ist ein guter Fang! Es tritt auf, da einer der Zwischenwerte ~ 65807 ist. Dies ist ein großer Wert, nachdem Gamma angewendet wurde und Python überläuft. Dasselbe tritt in J auf, da es auf derselben Berechnung beruht.
Meilen
1

PARI / GP, 30 Bytes

x->solve(t=1,x+1,gamma(t+1)-x)

Findet eine Lösung zwischen 1und x+1. Leider xist die Obergrenze für Eingaben wie nicht groß genug 1.5.

Christian Sievers
quelle
1

Mathematica, 26 Bytes

Noch eine Mathematica-Lösung!

Das Lösen von Gleichungen kann immer zu einem Minimierungsproblem werden.

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

Findet das Argument, das den Unterschied zwischen der linken und der rechten Seite der Gleichung minimiert.

Die Verwendung von NArgMin anstelle von NMinimize erzwingt, dass die Ausgabe nur das gewünschte Ergebnis und nicht die übliche ausführliche regelbasierte Ausgabe ist (und spart ein Byte!)

Kelly Lowder
quelle
0

C mit libm, 111

Update - behoben für Input 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)ist eine monoton ansteigende Funktion über den fraglichen Bereich, shis ist nur eine binäre Suche, bis der Unterschied zwischen aufeinanderfolgenden Werten gering ist. Die untere Anfangsgrenze ist 0und die obere Anfangsgrenze ist2*x .

Ein- und Ausgabe erfolgt über einen Zeiger auf ein Double, das an die Funktion übergeben wird.

Ich bin mir ziemlich sicher, dass man hier tiefer Golf spielen kann - insbesondere glaube ich nicht, dass ich 4 lokale Doppel brauche, aber bisher sehe ich keine einfache Möglichkeit, dies zu reduzieren.

Online ausprobieren - Erstellt (Verknüpfung mit libm) und läuft in einem Bash-Skript.

Mild ungolfed:

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;
    }
}
Digitales Trauma
quelle