Odwrotna funkcja Pi

17

Funkcja Pi jest rozszerzeniem silni na liczby rzeczywiste (lub nawet liczby zespolone). Dla liczb całkowitych n , Π (n) = n! , ale aby uzyskać definicję rzeczywistą, definiujemy ją za pomocą całki:

Pi (z) = całka t od 0 do nieskończoności e ^ -tt ^ z dt

W tym wyzwaniu odwrócimy funkcję Π .

Biorąc pod uwagę liczbę rzeczywistą z ≥ 1 , znajdź dodatnią x taką, że Π (x) = z . Twoja odpowiedź musi być dokładna co najmniej 5 cyfr dziesiętnych.


Przykłady:

120 -> 5.0000
10 -> 3.39008
3.14 -> 2.44815
2017 -> 6.53847
1.5 -> 1.66277
orlp
źródło
4
Zauważ, że częściej ludzie używają funkcji Gamma (Γ). Π (x) = Γ (x + 1) . Ale IMO Γ jest przesuniętą obrzydliwością, a Π jest prawdziwym rozszerzeniem silni.
orlp
1
Wellp, to rozszerzenie serii wystarczy, by mnie przestraszyć ... i.imgur.com/ttgzDSJ.gif
Magic Octopus Urn
1
Wszystkie podane przykłady mają również inne rozwiązania, na przykład 120 -> -0.991706. Wynika to z tego, że Π (x) przechodzi w nieskończoność, gdy x idzie w prawo do -1. Być może masz na myśli, że x> 0 również.
Greg Martin
@GregMartin Dodano również.
orlp
1
Istnieje kilka powodów, aby preferować przesuniętą wersję, mimo że wydaje się to nienaturalne. Zobacz np. Tę odpowiedź na MathOverflow, a także inne na tej stronie.
Ruslan

Odpowiedzi:

8

Mathematica, 17 15 27 bajtów

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

Dane wyjściowe wyglądają {{x -> n}}, gdzie njest rozwiązanie, które może być niedozwolone.

Pavel
źródło
7

Pyth, 4 bajty

.I.!

Program, który pobiera liczbę i wypisuje wynik.

Zestaw testowy

Jak to działa

.I.!    Program. Input: Q
.I.!GQ  Implicit variable fill
.I      Find x such that:
  .!G    gamma(x+1)
     Q   == Q
        Implicitly print
TheBikingViking
źródło
5

MATL , 13 bajtów

1`1e-5+tQYgG<

Używa to liniowego wyszukiwania w krokach od 1e-5początku 1. Jest więc bardzo powolny i upływa limit czasu w internetowym kompilatorze.

Aby to przetestować, poniższy link zastępuje 1e-5wymaganie dotyczące dokładności przez 1e-2. Wypróbuj online!

Wyjaśnienie

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
źródło
3

GeoGebra , 25 bajtów

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

Wprowadzony w danych wejściowych CAS i oczekuje wprowadzenia liczby w komórce arkusza kalkulacyjnego A1. Zwraca tablicę jednoelementową formularza {x = <result>}.

Oto gif z wykonania:

Realizacja programu

Jak to działa

Nhipotetycznie Solvenastępujące równanie :, Gamma(x+1)=A1z wartością początkową x=1.

TheBikingViking
źródło
Czy gwarantuje to zwrócenie liczby dodatniej i czy działa w przypadku wartości 1,5, która popsuła kilka odpowiedzi?
Pavel
@Pavel Mogę potwierdzić, że to działa 1.5. Nie byłem w stanie dowiedzieć się, jakiego algorytmu używa GeoGebra do rozwiązywania liczb, ale początkowa wartość x=1dała czysto pozytywne odpowiedzi dla każdej wartości, którą wypróbowałem.
TheBikingViking
2

MATLAB, 59 bajtów

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

Jest to anonimowa funkcja, która znajduje minimalizator kwadratowej różnicy między funkcją Pi i jej wejściem, zaczynając od 1, z bardzo małą tolerancją (podaną przez eps), aby osiągnąć pożądaną precyzję.

Przypadki testowe (uruchamiane na 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

Możesz spróbować online w Octave, ale niestety niektóre wyniki nie mają wymaganej precyzji.

Luis Mendo
źródło
2

J, 86 33 bajtów

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

Używa metody Newtona z logiem Pi, aby uniknąć przepełnienia.

Jest to poprzednia wersja, która oblicza log Gamma przy użyciu przybliżenia Stirlinga. Rozmiar kroku (1e3) i liczbę terminów w log Gamma (3) można zwiększyć, aby uzyskać możliwie wyższą dokładność kosztem wydajności.

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

Kolejna wersja, która oblicza współczynniki w locie

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

Wypróbuj online! i zobaczyć, jak warunki się zbiegają .

Wyjaśnienie

((]-(-~^.@!)%[:^.@!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
mile
źródło
2

Mathematica, 21 bajtów

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

FindRoot stosuje metodę Newtona wewnętrznie, gdy istnieje wartość początkowa.

Dwie poniższe metody stosują metodę Newtona bezpośrednio.

Alternatywnie przy użyciu FixedPoint 45 bajtów

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

Bardziej precyzyjna implementacja metody Newtona do rozwiązania tego, ponieważ Mathematica może obliczyć pochodną bezpośrednio, zamiast ją przybliżać.

Wielokrotne zastępowanie reguł byłoby krótsze, ale istnieje limit (65536) liczby iteracji, które może wykonać, które mogą zostać trafione, FixedPointale nie ma limitu.

Alternatywne użycie reguł, 38 bajtów

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

Wizerunek

mile
źródło
1

Galaretka , 34 bajty

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

Wypróbuj online! lub Zobacz wartości pośrednie, gdy się zbiegają .

Implementacja kombinacji metody Newtona i aproksymacji pochodnej (metoda sieczna) w celu obliczenia odwrotności Π ( n ).

Zamiast tego rozwiązuje odwrotność log ( Π ( n )), aby uniknąć przepełnienia.

Zaczyna się od wstępnego odgadnięcia x 0 = y +1, gdzie y = log ( Π ( n )). Następnie iteruje do konwergencji za pomocą x n +1 = x n - (log ( Π ( x n )) - y ) / (log (( Π (1.001 * x n )) - log ( Π ( x n ))) / (0,001 * x n )).

mile
źródło
3
Dostaję błąd przy wprowadzaniu1.5
Luis Mendo,
@LuisMendo Wow, to dobry haczyk! Dzieje się tak, ponieważ jedna z wartości pośrednich wynosi ~ 65807, co jest ogromną wartością po zastosowaniu gamma i przepełnieniu Pythona. To samo dzieje się w J, ponieważ opiera się na tym samym obliczeniu.
mile
1

PARI / GP, 30 bajtów

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

Znajduje rozwiązanie między 1i x+1. Niestety, xnie jest wystarczająco duży jako górna granica dla takich danych wejściowych 1.5.

Christian Sievers
źródło
1

Mathematica, 26 bajtów

Jeszcze jedno rozwiązanie Mathematica!

Rozwiązywanie równań zawsze można przekształcić w problem minimalizacji.

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

Znajduje argument, który minimalizuje różnicę między lewą i prawą stroną równania.

Użycie NArgMin zamiast NMinimize wymusza, aby wynik był po prostu pożądanym wynikiem, a nie zwykłym pełnym wyjściem opartym na regułach (i oszczędza bajt!)

Kelly Lowder
źródło
0

C z libm, 111

Aktualizacja - naprawiono dla danych wejściowych 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)jest monotonicznie rosnącą funkcją w danym zakresie, shis jest po prostu wyszukiwaniem binarnym, dopóki różnica między kolejnymi wartościami nie będzie niewielka. Początkowa dolna granica to, 0a początkowa górna granica to 2*x.

Wejście i wyjście odbywa się za pomocą wskaźnika do podwójnego przekazanego do funkcji.

Jestem prawie pewien, że można pograć w golfa głębiej - w szczególności nie sądzę, żebym potrzebował 4 miejsc do gry podwójnej, ale jak dotąd nie widzę łatwego sposobu na zmniejszenie tego.

Wypróbuj online - kompiluje (łączy z libm) i działa w skrypcie bash.

Lekko niegolfowany:

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;
    }
}
Cyfrowa trauma
źródło