Gamma Function Golf
C++14, 86 85 81 bytes
[](auto t){auto v=1.;for(int x=1;x<1e9;++x)v*=pow(1+1./x,t)/(1+t/x);return v/t;};
I didn't spend much time on this one. I just looked on approximation that seemed the easiest to implement (in the manner of bytes). It will take some time to compute the value (since the loop is over all positive integers), but time limitation is not specified in the challenge. It is anonymous function (lambda), which takes any argument (convertible to T
on which pow(double, T)
and operator/(T,int)
can be called) and returns double
.
Ungolfed with usage
#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
}
Minkolang 0.12, 35 34 25 bytes
n$zl8;dz;z$:r[i1+dz+$:*]N
This does halt with an error (on trying to divide by 0), but that is allowed as per Meta consensus. Add a .
at the end for a program that halts normally. Try all test cases at once. (The loop iterates only 1e4 times so it would finish sooner rather than later.)
Explanation
Zereges used one of the alternative, infinite product definitions. As it turns out, the other is much more amenable to implement in Minkolang.
This is a limit as n
goes to infinity, which means that I can calculate both n!
and (t+n)
as I go. So I take out 1/t
(because 0!=1
) and n^t
because that one cannot be calculated sequentially without knowing the ending value of n
. As it happens, because n
is the limit, I can use it twice. Once as a factor in the calculation and once as the number of times to run the loop.
An sequential infinite product has to start with something, usually 1. In this case, it's n^t/t
. In the body of the loop, I calculate k/(t+k)
and multiply this with the product so far. At the end, the whole product has been calculated and output. This is essentially what my program does, with n
high enough that the answer is precise enough.
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
As there is no .
, it wraps around and starts over. However, n
now produces -1
because the input is empty, which eventually leads to attempting to divide by 0, which halts the program.
Julia, 141 bytes
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])))
This creates an unnamed lambda function that accepts a real number and returns a real number. It uses Spounge's approximation to compute Gamma.
Ungolfed:
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