Fonction Gamma Golf


17

Étant donné un nombre réel tdans (-10^9,13)(non compris -10^9ou 13) comme entrée, sortie Γ(t), également connue sous le nom de fonction Gamma , qui est définie comme suit:

définition de la fonction gamma

Vous ne pouvez pas utiliser une fonction gamma intégrée pour résoudre cette tâche, ni utiliser des fonctions d'intégration numériques ou symboliques intégrées. Votre sortie doit être précise à 6 chiffres significatifs ou à l'intérieur 10^-6de la valeur réelle, la valeur la moins restrictive étant retenue. La fonction Gamma intégrée de Python sera utilisée pour déterminer la valeur réelle. Vous pouvez supposer qu'il Γ(t)est défini - c'est-à-dire qu'il s'agit d' tun nombre réel positif ou d'un nombre réel négatif non entier - et cela |Γ(t)| ≤ 10^9. Voici un programme de référence que vous pouvez utiliser pour obtenir les valeurs réelles, en utilisant la fonction Gamma intégrée de Python.

Exemples

1 -> 1.000000
-2.5 -> -0.945309
3.14159265 -> 2.288038
-2.71828182846 -> -0.952682
12 -> 39916800.000000
0.5 -> 1.772454
8.675309 -> 20248.386956
-10.1 -> -0.000002

Règles

  • C'est le , donc la réponse la plus courte (en octets) l'emporte.
  • Les failles standard sont interdites.
  • L'entrée et la sortie peuvent être effectuées de la manière considérée comme standard pour votre langue.
  • Vous pouvez écrire un programme complet, une fonction ou tout ce qui est normalement considéré comme une réponse valide pour votre langue

Classement

L'extrait de pile au bas de cet article génère le classement à partir des réponses a) comme une liste des solutions les plus courtes par langue et b) comme un classement général.

Pour vous assurer que votre réponse s'affiche, veuillez commencer votre réponse avec un titre, en utilisant le modèle Markdown suivant:

## Language Name, N bytes

Nest la taille de votre soumission. Si vous améliorez votre score, vous pouvez conserver les anciens scores dans le titre, en les barrant. Par exemple:

## Ruby, <s>104</s> <s>101</s> 96 bytes

Si vous souhaitez inclure plusieurs nombres dans votre en-tête (par exemple, parce que votre score est la somme de deux fichiers ou que vous souhaitez répertorier les pénalités de drapeau d'interprète séparément), assurez-vous que le score réel est le dernier numéro de l'en-tête:

## Perl, 43 + 2 (-p flag) = 45 bytes

Vous pouvez également faire du nom de la langue un lien qui apparaîtra ensuite dans l'extrait de code:

## [><>](http://esolangs.org/wiki/Fish), 121 bytes


1
Veuillez fournir des limites explicites pour t telles que | gamma (t) | <10 ^ 9
flawr

Le lien n'est pas une implémentation de référence, ...
sergiol

@sergiol Reformulé
Mego

Réponses:


2

Pyth, 21 octets

Comme pour ma réponse TI-BASIC, je n'ai pas pu tester cela avec les 8 ^ 10 itérations complètes, mais tout semble bien avec des cas plus petits.

cu*Gc^hc1HQhcQHS^8T1Q

Explication:

                            [implicit: Q=input]
                ^8T         8**10
               S^8T         [1,2,3,...,8**10]
  *Gc^hc1HQhcQH             lambda G,H:G*(1+1/H)**Q/(1+Q/H)
                   1        Base case
 u*Gc^hc1HQhcQHS^8T1        Reduce with base case 1
c                   Q       Divide by Q

Essayez-le ici avec 2000 itérations au lieu de 8 ^ 10.


10

C ++ 14, 86 85 81 octets

[](auto t){auto v=1.;for(int x=1;x<1e9;++x)v*=pow(1+1./x,t)/(1+t/x);return v/t;};

Je n'ai pas passé beaucoup de temps sur celui-ci. Je viens de regarder l'approximation qui semblait la plus simple à mettre en œuvre (à la manière des octets). Il faudra un certain temps pour calculer la valeur (puisque la boucle est sur tous les entiers positifs), mais la limitation de temps n'est pas spécifiée dans le défi. C'est une fonction anonyme (lambda), qui prend n'importe quel argument (convertible en Tsur lequel pow(double, T)et operator/(T,int)peut être appelé) et retournedouble .

Ungolfed avec l'utilisation

#include <iostream>
int main()
{
    auto r = [](auto t)
    {
        auto v = 1.;
        for (int x = 1; x < 1e9; ++x)
            v *= pow(1 + 1. / x, t) / (1 + t / x);
        return v / t;
    };
    std::cout << r(-2.71828182846); // outputs -0.952682
}

@Mego Bien sûr que ça l'est! Merci.
Zereges

Alors, quelle valeur obtenez-vous pour -10 ^ 9 et pour 10 ^ 9? Je veux d'abord savoir dans quelle mesure vos affaires fonctionnent avant d'obtenir mon vote positif.
flawr

Le compilateur Microsoft @Mego n'a besoin d'aucune de ces inclusions.
Zereges

@MegoMicrosoft (R) C/C++ Optimizing Compiler Version 19.00.23026 for x86
Zereges

Le programme @flawr Mine affiche 0 pour gamma(-10e9)mais OP a déclaré que seuls les paramètres pour lesquels une fonction gamma est définie peuvent être pris en compte. gamma(10e9)retours inf, alors que Python fonction Gamma intégré seront utilisées pour déterminer la valeur réelle ditOverflowError: math range error
Zereges

7

Minkolang 0,12 , 35 34 25 octets

n$zl8;dz;z$:r[i1+dz+$:*]N

Cela s'arrête avec une erreur (en essayant de diviser par 0), mais cela est autorisé selon le consensus Meta . Ajoutez un .à la fin pour un programme qui s'arrête normalement. Essayez tous les cas de test en même temps.(La boucle n'itère que 1e4 fois, donc elle se terminera plus tôt que tard.)

Explication

Zereges a utilisé l'une des définitions de produits alternatives infinies . Il s'avère que l'autre est beaucoup plus facile à mettre en œuvre à Minkolang.

Formulation alternative d'Euler de la fonction gamma

C'est une limite qui nva à l'infini, ce qui signifie que je peux calculer les deux n!et au (t+n)fur et à mesure. Je retire donc 1/t(parce que 0!=1) et n^tparce que celui-ci ne peut pas être calculé séquentiellement sans connaître la valeur finale de n. En l'occurrence, parce que nc'est la limite, je peux l'utiliser deux fois. Une fois comme facteur dans le calcul et une fois comme nombre de fois pour exécuter la boucle.

Un produit infini séquentiel doit commencer par quelque chose, généralement 1. Dans ce cas, c'est n^t/t. Dans le corps de la boucle, je calcule k/(t+k)et multiplie cela avec le produit jusqu'à présent. À la fin, le produit entier a été calculé et produit. C'est essentiellement ce que fait mon programme, avec nsuffisamment de précision pour que la réponse soit suffisamment précise.

version éclatée du produit infini

n                            Take number from input
 $z                          Store it in the register (this is t; retrieved with z)
   l8;                       10^8 (this is n, the limit)
      d                      n,n
       z;                    n,n^t
         z$:                 n,n^t/t
            r                Reverse stack -> n^t/t,n
             [               For loop that runs n times
              i1+            k
                 d           k,k
                  z+         k,t+k
                    $:       k/(t+k)
                      *      Multiply
                       ]N    Close for loop and output as integer

Comme il n'y en a pas ., il s'enroule et recommence. Cependant, nproduit maintenant -1parce que l'entrée est vide, ce qui conduit finalement à tenter de diviser par 0, ce qui interrompt le programme.


5

Julia, 141 octets

z->(z-=1;a=90;c(k)=(k=big(k);(-1)^(k-1)/factorial(k-1)*(a-k)^(k-.5)*exp(a-k));(z+a)^(z+.5)*exp(-z-a)*(√(2π)+sum([c(k)/(z+k)for k=1:a-1])))

Cela crée une fonction lambda sans nom qui accepte un nombre réel et renvoie un nombre réel. Il utilise l'approximation de Spounge pour calculer le gamma.

Non golfé:

function Γ(z::Real)
    # Spounge's approxmation is for Γ(z+1), so subtract 1
    z -= 1

    # Choose a number for the constant a, which determines the
    # bound on the error
    a = 90

    # Define a function for the sequence c_k
    function c(k::Integer)
        # Convert k to a BigInt
        k = big(k)
        return (-1)^(k-1) / factorial(k-1) * (a-k)^(k-1/2) * exp(a-k)
    end

    # Compute the approximation
    return (z+a)^(z+1/2) * exp(-z-a) * (√(2π) + sum([c(k)/(z+k) for k=1:a-1]))
end

Golf très , très tardif, mais z->(z-=1;a=90;c(k)=(k=big(k);(-1)^~-k/factorial(k-1)*(a-k)^(k-.5)*exp(a-k));(z+a)^(z+.5)*exp(-z-a)*(√(2π)+sum(c(k)/(z+k)for k=1:a-1)))devrait fonctionner pour 137 octets (au moins dans Julia 0.6)
M. Xcoder

3

Japt, 45 octets

Japt est une version abrégée de Ja vaScri pt . Interprète

$for(V=X=1;X<1e9;)$V*=(1+1/X pU /(1+U/X++;V/U

Bien sûr, 1e9 = 1 000 000 000 d'itérations prend une éternité, donc pour les tests, essayez de remplacer le 9par un 6. (1e6 est précis à ~ 5 chiffres significatifs. L'utilisation de 1e8 sur une entrée de 12suffit pour obtenir les six premiers.)

Résultats du cas de test: (en utilisant la précision 1e7)

       1:  1
    -2.5: -0.9453083...
      pi:  2.2880370...
      -e: -0.9526812...
      12:  39916536.5...
     0.5:  1.7724538...
8.675309:  20248.319...
   -10.1: -0.0000022...

Comment ça fonctionne

         // Implicit: U = input number
$for(    // Ordinary for loop.
V=X=1;   //  Set V and X to 1.
X<1e9;)$ //  Repeat while X is less than 1e9.
V*=      // Multiply V by:
(1+1/X   //  1 plus (1 over X),
pU /     //  to the power of U, divided by
(1+U/X++ //  1 plus (U over X). Increment X by 1.
;V/U     // Output the result of (V over U).

3

TI-BASIC, 35 octets

Input Z
1
For(I,1,ᴇ9
Ans(1+I⁻¹)^Z/(1+Z/I
End
Ans/Z

Celui-ci utilise le même algorithme que Zereges.

Mise en garde: je n'ai pas réellement testé cela avec les itérations 1e9 complètes; en fonction du temps pris pour des valeurs plus petites, je m'attends à ce que le temps d'exécution soit de l'ordre des mois . Cependant, il semble converger et il ne devrait pas y avoir de problème avec les erreurs d'arrondi. TI stocke les nombres sous forme de nombres décimaux avec 14 chiffres de précision.


Vous ne l'avez pas testé?!
TanMath

1
@TanMath je le ferais, mais j'ai besoin de ma calculatrice pour un examen final le mois prochain.
lirtosiast

3

Python 3, 74 68 78 73 octets

Merci @Mego et @xnor

Ceci est une traduction de la réponse C ++ par Zereges. Fondamentalement, il s'agit d'une autre définition de la fonction gamma, donc plus précise (et ce qui est génial, c'est qu'elle utilise moins d'octets!)

Je suis désolé pour toutes les erreurs!

def g(z,v=1):
 for i in range(1,10**9):v*=(1+1/i)**z/(1+z/i)
 return v/z

1
Le +1sur la gamme n'a pas d'importance lorsque vous avez affaire à des milliards. En outre, vous devez spécifier qu'il s'agit de Python 3 - vous auriez besoin from __future__ import divisiond'une division flottante et de quelques téraoctets de RAM pour faire face au fait que rangerenvoie une liste en Python 2. De plus, vous pouvez remplacer le 1.0s par 1s et raser 4 octets.
Mego

2
@TanMath: ^est xor, ne voulais -tu pas dire **pour l'exponentiation?
jermenkoo

3
int(1e9)est juste 10**9, et vous n'avez pas besoin des parens autour (1+1/i)**z.
xnor

3

Python, 348 448 407 390 389 octets

Un merci spécial à @Mego!

Un 448 barré est (presque) toujours un 448! : p

Ceci est basé sur l'approximation de Lanzcos. Golfé d' ici

from cmath import*
C=[0.9999999999998099,676.5203681218851,-1259.1392167224028,771.3234287776531,-17‌6.6150291621406,12.507343278686905,-0.13857109526572012,9.984369578019572e-6,1.5‌​056327351493116e-7]
def g(z):
 z-=1;if z.real<0.5:return pi/(sin(pi*z)*gamma(1-z))
 else:
  x=C[0]
  for i in range(1,9):x+=C[i]/(z+i)
  t=z+7.5;return sqrt(2*pi)*t**(z+0.5)*exp(-t)*x

1
Veuillez jouer votre soumission au minimum en supprimant les espaces blancs (les espaces avant et après - = et dedans import *par exemple) et en utilisant un nom de fonction à un caractère. Notez également que vous ne devez prendre en charge que les entrées réelles.
lirtosiast

@ThomasKwa Je l'ai édité. Ma version originale n'a pas fonctionné, en voici une plus récente.
TanMath

@Mego édité ...
TanMath

Cela provoque une erreur de récursivité - supprimez le z-=1;dans la première ligne de gammapour le corriger. Vous devez également renommer gammaà gdes octets sauvetages et pour éviter les conflits de noms avec cmath.gamma. Supprimez également les zéros non significatifs.
Mego

1

Julia, 41 octets

x->prod([(1+1/i)^x/(1+x/i)for i=1:1E7])/x

Ceci est une traduction de la réponse C ++ de Zereges. Alors que mon autre réponse Julia se termine instantanément, c'est plutôt lent. Il calcule les cas de test en quelques secondes chacun sur mon ordinateur.

Non golfé:

function f(x::Real)
    prod([(1 + 1/i)^x / (1 + x/i) for i = 1:1E7]) / x
end

1

Prolog, 114 octets

Ceci est une traduction de la réponse C ++ de Zereges.

q(F,F,V,Z):-X is V/Z,write(X).
q(F,T,V,Z):-W is(1+1/F)**Z/(1+Z/F)*V,I is F+1,q(I,T,W,Z).
p(N):-q(1.0,1e9,1,N),!.

Essayez-le en ligne ici
Exécutez-le avec une requête du formulaire:

p(12).

L'exécuter avec 1e9 récursions prend environ 15 minutes.
Si vous le diminuez à 1e6, cela prend environ 1 seconde, ce qui rend les tests plus faciles (mais moins précis).
L'exécuter dans un interprète sur votre ordinateur / ordinateur portable est également plus rapide pour la plupart des gens.


En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.