Fonction Pi inverse

17

La fonction Pi est une extension de la factorielle sur les réels (ou même des nombres complexes). Pour les entiers n , Π (n) = n! , mais pour obtenir une définition sur les réels, nous la définissons en utilisant une intégrale:

Pi(z) = integral t from 0 to infinity e^-t t^z dt

Dans ce défi, nous allons inverser la fonction Π .

Étant donné un nombre réel z ≥ 1 , trouver x positif tel que Π (x) = z . Votre réponse doit être précise pour au moins 5 chiffres décimaux.


Exemples:

120 -> 5.0000
10 -> 3.39008
3.14 -> 2.44815
2017 -> 6.53847
1.5 -> 1.66277
orlp
la source
4
Notez que les gens utilisent plus souvent la fonction Gamma (Γ). Π (x) = Γ (x + 1) . Mais l'OMI Γ est une abomination décalée, et Π est la véritable extension de la factorielle.
orlp
1
Wellp, cette extension de la série suffit pour me faire peur ... i.imgur.com/ttgzDSJ.gif
Magic Octopus Urn
1
Tous les exemples que vous donnez ont également d'autres solutions, par exemple 120 -> -0.991706. En effet, Π (x) va à l'infini lorsque x va à -1 à partir de la droite. Vous voulez peut-être aussi insister sur le fait que x> 0.
Greg Martin
@GregMartin Ajouté également.
orlp
1
Il y a quelques raisons de préférer la version décalée, même si cela ne semble pas naturel. Voir par exemple cette réponse sur MathOverflow ainsi que d'autres sur cette page.
Ruslan

Réponses:

8

Mathematica, 17 15 27 octets

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

La sortie ressemble {{x -> n}}, où nest la solution, qui peut ne pas être autorisée.

Pavel
la source
7

Pyth, 4 octets

.I.!

Un programme qui prend l'entrée d'un nombre et imprime le résultat.

Suite de tests

Comment ça fonctionne

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

MATL , 13 octets

1`1e-5+tQYgG<

Cela utilise la recherche linéaire par étapes de 1e-5départ 1. C'est donc terriblement lent et arrive à expiration dans le compilateur en ligne.

Pour le tester, le lien suivant remplace l' 1e-5exigence de précision par 1e-2. Essayez-le en ligne!

Explication

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
la source
3

GeoGebra , 25 octets

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

Entré dans l'entrée CAS et attend l'entrée d'un nombre dans la cellule de la feuille de calcul A1. Renvoie un tableau à un élément du formulaire {x = <result>}.

Voici un gif de l'exécution:

Exécution du programme

Comment ça fonctionne

Numeriquement Solvel'équation suivante :, Gamma(x+1)=A1avec valeur de départ x=1.

TheBikingViking
la source
Est-il garanti de renvoyer un nombre positif et cela fonctionne-t-il pour 1,5, ce qui a cassé plusieurs réponses?
Pavel
@ Pavel Je peux confirmer que cela fonctionne 1.5. Je n'ai pas pu découvrir quel algorithme GeoGebra utilise pour la résolution numérique, mais la valeur initiale de x=1a donné des réponses purement positives pour chaque valeur que j'ai essayée.
TheBikingViking
2

MATLAB, 59 octets

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

Il s'agit d'une fonction anonyme qui trouve le minimiseur de la différence au carré entre la fonction Pi et son entrée, à partir de 1, avec une très petite tolérance (donnée par eps) pour atteindre la précision souhaitée.

Cas de test (exécutés sur 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

Vous pouvez l' essayer en ligne dans Octave, mais malheureusement certains résultats manquent de la précision requise.

Luis Mendo
la source
2

J, 86 33 octets

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

Utilise la méthode de Newton avec log Pi pour éviter le débordement.

Il s'agit de la version précédente qui calcule le log Gamma en utilisant l'approximation de Stirling. La taille de pas (1e3) et le nombre de termes dans le log Gamma (3) peuvent être augmentés pour une précision éventuellement plus élevée au détriment des performances.

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

Une autre version qui calcule les termes des coefficients à la volée

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

Essayez-le en ligne! et de voir les termes converger .

Explication

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

Mathematica, 21 octets

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

FindRoot applique la méthode de Newton en interne lorsqu'il existe une valeur initiale.

Les deux méthodes ci-dessous appliquent directement la méthode de Newton.

Alternative utilisant FixedPoint 45 octets

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

Une implémentation plus précise de la méthode de Newton pour résoudre ce problème car Mathematica peut calculer la dérivée directement au lieu de l'approximer.

L'utilisation de règles à remplacer de manière répétée serait plus courte, mais il y a une limite (65536) au nombre d'itérations qu'elle peut effectuer qui pourraient être atteintes alors qu'elle FixedPointn'a pas de limite.

Alternative utilisant des règles, 38 octets

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

Image

miles
la source
1

Gelée , 34 octets

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

Essayez-le en ligne! ou Affichez les valeurs intermédiaires lorsqu'elles convergent .

Une implémentation de la combinaison de J de la méthode de Newton et de l'approximation dérivée (méthode sécante) pour calculer l'inverse de Π ( n ).

Il résout plutôt l'inverse de log ( Π ( n )) afin d'éviter un débordement.

Il commence par une estimation initiale x 0 = y +1 où y = log ( Π ( n )). Ensuite, il itère jusqu'à la convergence en utilisant x n +1 = x n - (log ( Π ( x n )) - y ) / (log (( Π (1.001 * x n )) - log ( Π ( x n ))) / (0,001 * x n )).

miles
la source
3
Je reçois une erreur avec la saisie1.5
Luis Mendo
@LuisMendo Wow c'est une bonne prise! Cela se produit car l'une des valeurs intermédiaires est ~ 65807, ce qui est une valeur énorme après l'application du gamma et le débordement de Python. La même chose se produit dans J car elle repose sur le même calcul.
miles
1

PARI / GP, 30 octets

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

Trouve la solution entre 1et x+1. Malheureusement, ce xn'est pas assez grand comme limite supérieure pour l'entrée comme 1.5.

Christian Sievers
la source
1

Mathematica, 26 octets

Encore une autre solution Mathematica!

La résolution d'équations peut toujours devenir un problème de minimisation.

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

Recherche l'argument qui minimise la différence entre les côtés gauche et droit de l'équation.

L'utilisation de NArgMin plutôt que de NMinimize force la sortie à être le résultat souhaité plutôt que la sortie verbeuse habituelle basée sur des règles (et cela économise un octet!)

Kelly Lowder
la source
0

C avec libm, 111

Mise à jour - corrigé pour l'entrée 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)est une fonction qui augmente de façon monotone sur la plage en question, shis n'est qu'une recherche binaire jusqu'à ce que la différence entre les valeurs successives soit petite. La borne inférieure de départ est 0et la borne supérieure de départ est 2*x.

L'entrée et la sortie se font via un pointeur vers un double passé à la fonction.

Je suis presque sûr que cela peut être approfondi - en particulier, je ne pense pas avoir besoin de 4 doubles locaux, mais jusqu'à présent, je ne vois pas de moyen facile de réduire cela.

Essayez-le en ligne - Construit (liaison avec libm) et s'exécute dans un script bash.

Légèrement non golfé:

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;
    }
}
Traumatisme numérique
la source