Golf z funkcją gamma

17

Biorąc pod uwagę liczbę rzeczywistą tw (-10^9,13)(bez uwzględnienia -10^9lub 13) jako dane wejściowe, wyjściowe Γ(t), znane również jako funkcja gamma , która jest zdefiniowana następująco:

definicja funkcji gamma

Nie możesz użyć wbudowanej funkcji Gamma do rozwiązania tego zadania, ani nie możesz użyć wbudowanych liczbowych lub symbolicznych funkcji integracji. Twój wynik powinien być dokładny do 6 cyfr znaczących lub w granicach 10^-6rzeczywistej wartości, w zależności od tego, która wartość jest mniej restrykcyjna dla danej wartości. Do określenia rzeczywistej wartości zostanie wykorzystana wbudowana funkcja Gamma Pythona. Możesz założyć, że Γ(t)jest zdefiniowany - to tjest albo dodatnia liczba rzeczywista, albo niecałkowita ujemna liczba rzeczywista - i to |Γ(t)| ≤ 10^9. Oto program referencyjny, którego możesz użyć do uzyskania rzeczywistych wartości, używając wbudowanej funkcji Gamma Pythona.

Przykłady

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

Zasady

  • To jest , więc wygrywa najkrótsza odpowiedź (w bajtach).
  • Standardowe luki są zabronione.
  • Dane wejściowe i wyjściowe można wykonywać w dowolny sposób uznany za standardowy dla Twojego języka.
  • Możesz napisać pełny program, funkcję lub cokolwiek, co zwykle jest uważane za prawidłową odpowiedź dla twojego języka

Tabela liderów

Fragment kodu na dole tego postu generuje tabelę wyników na podstawie odpowiedzi a) jako lista najkrótszych rozwiązań dla każdego języka oraz b) jako ogólna tabela wyników.

Aby upewnić się, że twoja odpowiedź się pojawi, zacznij od nagłówka, korzystając z następującego szablonu Markdown:

## Language Name, N bytes

gdzie Njest rozmiar twojego zgłoszenia. Jeśli poprawić swój wynik, to może zachować stare porachunki w nagłówku, uderzając je przez. Na przykład:

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

Jeśli chcesz umieścić w nagłówku wiele liczb (np. Ponieważ twój wynik jest sumą dwóch plików lub chcesz osobno wymienić kary za flagi tłumacza), upewnij się, że rzeczywisty wynik jest ostatnią liczbą w nagłówku:

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

Możesz także ustawić nazwę języka jako link, który pojawi się we fragmencie:

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

Mego
źródło
1
Proszę podać wyraźne granice dla t takie, aby | gamma (t) | <10 ^ 9
flawr
Link nie jest implementacją referencyjną, ...
sergiol
@sergiol Rewordeded it
Mego

Odpowiedzi:

2

Pyth, 21 bajtów

Podobnie jak w przypadku mojej odpowiedzi TI-BASIC, nie byłem w stanie przetestować tego z pełnymi iteracjami 8 ^ 10, ale wszystko wydaje się dobre w przypadku mniejszych przypadków.

cu*Gc^hc1HQhcQHS^8T1Q

Wyjaśnienie:

                            [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

Wypróbuj tutaj z 2000 iteracjami zamiast 8 ^ 10.

lirtosiast
źródło
10

C ++ 14, 86 85 81 bajtów

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

Nie spędziłem na tym dużo czasu. Właśnie przyjrzałem się przybliżeniu, które wydawało się najłatwiejsze do wdrożenia (w formie bajtów). Obliczenie wartości zajmie trochę czasu (ponieważ pętla obejmuje wszystkie dodatnie liczby całkowite), ale ograniczenie czasowe nie jest określone w wyzwaniu. Jest to funkcja anonimowa (lambda), która przyjmuje dowolny argument (zamienny Tna który pow(double, T)ioperator/(T,int) można wywołać można go wywołać) i zwraca double.

Nieprzyzwyczajony do użytkowania

#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
}
Zereges
źródło
@Mego Oczywiście, że tak! Dzięki.
Zereges
Więc jaką wartość dostajesz za -10 ^ 9 i za 10 ^ 9? Najpierw chcę wiedzieć, jak dobrze działają twoje rzeczy, zanim dostaniesz moją opinię.
flawr
Kompilator @Mego Microsoft nie potrzebuje żadnego z tych zestawów.
Zereges
@MegoMicrosoft (R) C/C++ Optimizing Compiler Version 19.00.23026 for x86
Zereges
@flawr Mój program wyjściowy 0, gamma(-10e9)ale OP stwierdził, że można brać pod uwagę tylko parametry, dla których zdefiniowano funkcję gamma. gamma(10e9)zwraca inf, podczas gdy wbudowana funkcja Gamma Pythona zostanie użyta do ustalenia rzeczywistej wartości mówiOverflowError: math range error
Zereges
7

Minkolang 0,12 , 35 34 25 bajtów

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

Zatrzymuje się to z błędem (przy próbie podzielenia przez 0), ale jest to dozwolone zgodnie z konsensusem Meta . Dodaj .na końcu program, który zatrzymuje się normalnie. Wypróbuj wszystkie przypadki testowe naraz. (Pętla iteruje tylko 1e4 razy, więc zakończy się wcześniej niż później).

Wyjaśnienie

Zereges użył jednej z alternatywnych, nieskończonych definicji produktu . Jak się okazuje, drugi jest znacznie łatwiejszy do wdrożenia w Minkolangu.

Euler's alternative formulation of the gamma function

Jest to limit n, który idzie do nieskończoności, co oznacza, że ​​mogę obliczyć jedno n!i drugie (t+n). Więc wyjmuję 1/t(ponieważ 0!=1) i n^tponieważ tego nie można obliczyć sekwencyjnie bez znajomości wartości końcowej n. Tak się składa, ponieważ njest to limit, mogę go użyć dwa razy. Raz jako czynnik w obliczeniach i raz jako liczba uruchomień pętli.

Sekwencyjny nieskończony produkt musi zaczynać się od czegoś, zwykle 1. W tym przypadku tak jest n^t/t. W treści pętli obliczam k/(t+k)i mnożę to do tej pory z produktem. Na koniec cały produkt został obliczony i wyprodukowany. Zasadniczo tak robi mój program, nwystarczająco wysoki, aby odpowiedź była wystarczająco precyzyjna.

exploded version of the infinite product

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

Ponieważ nie ma . , zawija się i zaczyna od nowa. Jednak nteraz produkuje, -1ponieważ dane wejściowe są puste, co ostatecznie prowadzi do próby podzielenia przez 0, co powoduje zatrzymanie programu.

El'endia Starman
źródło
5

Julia, 141 bajtów

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])))

Tworzy to nienazwaną funkcję lambda, która akceptuje liczbę rzeczywistą i zwraca liczbę rzeczywistą. To używa przybliżenie Spounge do obliczania gamma.

Nie golfowany:

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
Alex A.
źródło
Bardzo, bardzo późno golf, ale 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)))powinien działać na 137 bajtów (przynajmniej w Julii 0.6)
Pan Xcoder
3

Japt, 45 bajtów

Japt to skrócona wersja Ja vaScri pt . Interpretator

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

Oczywiście, 1e9 = 1 000 000 000 iteracji trwa wiecznie, więc w celu przetestowania spróbuj zastąpić 96. (1e6 jest dokładny do ~ 5 cyfr znaczących. Używanie 1e8 na wejściu12 wystarcza, aby uzyskać pierwsze sześć.)

Wyniki przypadku testowego: (przy użyciu precyzji 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...

Jak to działa

         // 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).
ETHprodukcje
źródło
3

TI-BASIC, 35 bajtów

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

Używa tego samego algorytmu co Zereges.

Zastrzeżenie: Właściwie nie testowałem tego z pełną iteracją 1e9; na podstawie czasu potrzebnego na mniejsze wartości oczekuję, że czas działania będzie rzędu miesięcy . Wydaje się jednak, że jest zbieżny i nie powinno być problemów z błędami zaokrąglania. TI przechowuje liczby jako liczby dziesiętne z 14 cyframi dokładności.

lirtosiast
źródło
Nie przetestowałeś tego ?!
TanMath,
1
@TanMath Chciałbym, ale potrzebuję kalkulatora do egzaminu końcowego w przyszłym miesiącu.
lirtosiast
3

Python 3, 74 68 78 73 bajtów

Dzięki @Mego i @xnor

To jest tłumaczenie odpowiedzi C ++ przez Zereges. Zasadniczo jest to alternatywna definicja funkcji gamma, a zatem bardziej dokładna (a co jest świetne, to, że zużywa mniej bajtów!)

Przepraszam za wszystkie błędy!

def g(z,v=1):
 for i in range(1,10**9):v*=(1+1/i)**z/(1+z/i)
 return v/z
TanMath
źródło
1
+1W zakresie nie ma znaczenia, gdy masz do czynienia z miliardów. Ponadto powinieneś sprecyzować, że jest to Python 3 - potrzebowałbyś from __future__ import divisionpodziału zmiennoprzecinkowego i kilku terabajtów pamięci RAM, aby poradzić sobie z faktem, że rangezwraca listę w Pythonie 2. Plus, możesz zastąpić 1.0s 1si ogolić 4 bajty.
Mego
2
@TanMath: czy Xor ^, nie miałeś na myśli **potęgowania?
jermenkoo,
3
int(1e9)jest po prostu 10**9i nie potrzebujesz wokół siebie parens (1+1/i)**z.
xnor
3

Python, 348 448 407 390 389 bajtów

Specjalne podziękowania dla @Mego!

Przekreślona 448 to (prawie) nadal 448! : p

Jest to oparte na przybliżeniu Lanzcos. Grał w golfa stąd

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
TanMath
źródło
1
Prześlij swoje zgłoszenie, przynajmniej usuwając białe spacje (spacje przed i po - = i import *na przykład) oraz używając jednoznakowej nazwy funkcji. Pamiętaj też, że musisz obsługiwać tylko rzeczywiste dane wejściowe.
lirtosiast
@ThomasKwa Zredagowałem to. Moja oryginalna wersja nie działała, tutaj jest nowsza.
TanMath,
@Mego edytowano ...
TanMath,
Powoduje to błąd rekurencji - usuń z-=1;pierwszy wiersz, gammaaby go naprawić. Powinieneś także zmienić nazwę gammanag na bajty i zapisuje w celu uniknięcia konfliktów z nazewnictwa cmath.gamma. Upuść także zewnętrzne początkowe zera.
Mego
1

Julia, 41 bajtów

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

To jest tłumaczenie odpowiedzi C ++ Zeregesa. Podczas gdy moja inna odpowiedź Julii kończy się natychmiast, jest to raczej powolne. Oblicza przypadki testowe w ciągu kilku sekund na moim komputerze.

Nie golfowany:

function f(x::Real)
    prod([(1 + 1/i)^x / (1 + x/i) for i = 1:1E7]) / x
end
Alex A.
źródło
1

Prolog, 114 bajtów

To jest tłumaczenie odpowiedzi C ++ Zeregesa.

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),!.

Wypróbuj online tutaj
Uruchom go za pomocą zapytania formularza:

p(12).

Uruchomienie go z rekurencjami 1e9 zajmuje około 15 minut.
Jeśli zmniejszysz go do 1e6, zajmie to około 1 sekundy, co ułatwia (ale mniej dokładne) testowanie.
Uruchomienie go w tłumaczu na twoim komputerze / laptopie jest prawdopodobnie również szybsze dla większości ludzi.

Emigna
źródło
0

Mathematica, 40 bajtów

NProduct[(1+1/n)^#/(1+#/n),{n,1,∞}]/#&
alephalpha
źródło