Gamma Function Golf


17

Dato un numero reale tin (-10^9,13)(escluso -10^9o 13) come input, output Γ(t), noto anche come funzione Gamma , che è definita come segue:

definizione della funzione gamma

Non è possibile utilizzare una funzione Gamma integrata per risolvere questo compito, né utilizzare le funzioni integrate di integrazione numerica o simbolica. L'output deve essere accurato su 6 cifre significative o all'interno 10^-6del valore effettivo, a seconda di quale sia il meno restrittivo per il valore dato. La funzione Gamma integrata di Python verrà utilizzata per determinare il valore effettivo. Si può presumere che Γ(t)sia definito - cioè tsia un numero reale positivo o un numero reale negativo non intero - e quello |Γ(t)| ≤ 10^9. Ecco un programma di riferimento che puoi usare per ottenere i valori effettivi, usando la funzione Gamma integrata di Python.

Esempi

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

Regole

  • Questo è , quindi vince la risposta più breve (in byte).
  • Sono vietate le scappatoie standard.
  • L'input e l'output possono essere eseguiti in qualunque modo sia considerato standard nella tua lingua.
  • Puoi scrivere un programma completo, una funzione o qualsiasi cosa che sia normalmente considerata una risposta valida per la tua lingua

Classifica

Lo snippet di stack nella parte inferiore di questo post genera la classifica dalle risposte a) come un elenco della soluzione più breve per lingua eb) come classifica generale.

Per assicurarti che la tua risposta venga visualizzata, ti preghiamo di iniziare la risposta con un titolo, utilizzando il seguente modello Markdown:

## Language Name, N bytes

dov'è Nla dimensione del tuo invio. Se si migliora il punteggio, è possibile mantenere i vecchi punteggi nel titolo, colpendoli. Per esempio:

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

Se si desidera includere più numeri nell'intestazione (ad es. Perché il punteggio è la somma di due file o si desidera elencare separatamente le penalità del flag dell'interprete), assicurarsi che il punteggio effettivo sia l' ultimo numero nell'intestazione:

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

Puoi anche rendere il nome della lingua un collegamento che verrà quindi visualizzato nello snippet:

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


1
Fornisci limiti espliciti per t tale che | gamma (t) | <10 ^ 9
flawr

Il link non è un'implementazione di riferimento, ...
sergiol

@sergiol Lo ha riformulato
Mego

Risposte:


2

Pyth, 21 byte

Come con la mia risposta TI-BASIC, non sono stato in grado di testarlo con le 8 ^ 10 iterazioni complete, ma tutto sembra a posto con casi più piccoli.

cu*Gc^hc1HQhcQHS^8T1Q

Spiegazione:

                            [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

Provalo qui con 2000 iterazioni invece di 8 ^ 10.


10

C ++ 14, 86 85 81 byte

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

Non ho trascorso molto tempo su questo. Ho appena guardato l'approssimazione che sembrava il più semplice da implementare (alla maniera dei byte). Ci vorrà del tempo per calcolare il valore (poiché il ciclo è su tutti i numeri interi positivi), ma la sfida non è specificata nella sfida. È una funzione anonima (lambda), che accetta qualsiasi argomento (convertibile Tin cui pow(double, T)e operator/(T,int)può essere chiamato) e restituisce double.

Ungolfed con uso

#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 Certo che lo è! Grazie.
Zereges,

Quindi quale valore ottieni per -10 ^ 9 e per 10 ^ 9? Voglio prima sapere come funzionano le tue cose prima di ottenere il mio voto.
Flawr

Il compilatore Microsoft @Mego non ha bisogno di nessuno di questi include.
Zereges,

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

@flawr Il mio programma emette 0 per gamma(-10e9)ma OP ha dichiarato che possono essere considerati solo i parametri, per i quali è definita la funzione gamma. gamma(10e9)restituisce inf, mentre la funzione Gamma integrata di Python verrà utilizzata per determinare il valore effettivo, diceOverflowError: math range error
Zereges,

7

Minkolang 0,12 , 35 34 25 byte

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

Questo si interrompe con un errore (nel tentativo di dividere per 0), ma ciò è consentito secondo il consenso Meta . Aggiungi .a alla fine per un programma che si arresta normalmente. Prova tutti i casi di test contemporaneamente. (Il ciclo scorre solo 1e4 volte, quindi finirà prima piuttosto che dopo.)

Spiegazione

Zereges utilizzava una delle alternative infinite, definizioni di prodotto . A quanto pare, l'altro è molto più suscettibile di implementazione in Minkolang.

Formulazione alternativa di Eulero della funzione gamma

Questo è un limite per quanto nriguarda l'infinito, il che significa che posso calcolare entrambi n!e (t+n)mentre vado. Quindi prendo 1/t(perché 0!=1) e n^tperché quello non può essere calcolato in sequenza senza conoscere il valore finale di n. Come succede, perché nè il limite, posso usarlo due volte. Una volta come fattore nel calcolo e una volta come numero di volte per eseguire il ciclo.

Un prodotto sequenziale infinito deve iniziare con qualcosa, di solito 1. In questo caso, lo è n^t/t. Nel corpo del ciclo, ho calcolato k/(t+k)e moltiplicato questo con il prodotto finora. Alla fine, l'intero prodotto è stato calcolato e prodotto. Questo è essenzialmente ciò che fa il mio programma, con un nlivello abbastanza alto che la risposta sia abbastanza precisa.

versione esplosa del prodotto infinito

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

Poiché non c'è ., si avvolge e ricomincia. Tuttavia, nora produce -1perché l'input è vuoto, il che alla fine porta a tentare di dividere per 0, il che interrompe il programma.


5

Julia, 141 byte

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

Questo crea una funzione lambda senza nome che accetta un numero reale e restituisce un numero reale. Usa l'approssimazione di Spounge per calcolare la 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

Golf molto , molto tardi, ma 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)))dovrebbe funzionare per 137 byte (almeno in Julia 0.6)
Mr. Xcoder

3

Japt, 45 byte

Japt è una versione abbreviata di Ja vaScri pt . Interprete

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

Naturalmente, 1e9 = 1.000.000.000 di iterazioni impiegano un'eternità, quindi per i test, prova a sostituire 9 con a 6. (1e6 ha una precisione di ~ 5 cifre significative. L'uso di 1e8 su un input di 12è sufficiente per ottenere i primi sei.)

Risultati del test: (usando la precisione 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...

Come funziona

         // 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 byte

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

Questo utilizza lo stesso algoritmo di Zereges.

Avvertenza: in realtà non l'ho testato con le iterazioni complete di 1e9; in base al tempo impiegato per valori più piccoli, mi aspetto che l'autonomia sia dell'ordine dei mesi . Tuttavia, sembra convergere e non dovrebbero esserci problemi con gli errori di arrotondamento. TI memorizza i numeri come numeri decimali con 14 cifre di precisione.


Non l'hai provato ?!
TanMath,

1
@TanMath lo farei, ma ho bisogno della mia calcolatrice per un esame finale il mese prossimo.
lirtosiast

3

Python 3, 74 68 78 73 byte

Grazie @Mego e @xnor

Questa è una traduzione della risposta C ++ di Zereges. Fondamentalmente, questa è una definizione alternativa della funzione gamma, quindi più accurata (e ciò che è bello è che usa meno byte!)

Mi dispiace per tutti gli errori!

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

1
L' +1intervallo non ha importanza quando hai a che fare con miliardi. Inoltre, dovresti specificare che si tratta di Python 3 - avresti bisogno from __future__ import divisiondella divisione float e di alcuni terabyte di RAM per far fronte al fatto che rangerestituisce un elenco in Python 2. Inoltre, puoi sostituire la 1.0s con se 1rasare 4 byte.
Mego

2
@TanMath: ^è xor, non volevi dire **esponenziazione?
jermenkoo,

3
int(1e9)è giusto 10**9e non hai bisogno delle parentesi (1+1/i)**z.
xnor

3

Pitone, 348 448 407 390 389 byte

Un ringraziamento speciale a @Mego!

Un 448 barrato è (quasi) ancora un 448! : p

Questo si basa sull'approssimazione di Lanzcos. Giocato a golf da qui

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
Si prega di giocare a golf inviando, almeno, rimuovendo gli spazi bianchi (gli spazi prima e dopo - = e in import *per esempio) e usando un nome di funzione di un carattere. Si noti inoltre che è necessario supportare solo input reali.
Lirtosiast

@ThomasKwa L'ho modificato. La mia versione originale non ha funzionato, eccone una nuova.
TanMath,

@Mego modificato ...
TanMath il

Ciò provoca un errore di ricorsione: rimuovere il z-=1;nella prima riga di gammaper risolverlo. Si dovrebbe anche cambiare titolo gammaper gper i byte salva e per evitare conflitti con cmath.gamma. Eliminare anche gli zeri iniziali estranei.
Mego

1

Julia, 41 byte

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

Questa è una traduzione della risposta C ++ di Zereges. Mentre la mia altra risposta di Julia termina istantaneamente, questa è piuttosto lenta. Calcola i casi di test in un paio di secondi ciascuno sul mio computer.

Ungolfed:

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

1

Prolog, 114 byte

Questa è una traduzione della risposta C ++ di 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),!.

Provalo online qui
Eseguilo con una query del modulo:

p(12).

L'esecuzione con 1e9 ricorsioni richiede circa 15 minuti.
Se lo si riduce a 1e6, sono necessari circa 1 secondo, il che semplifica i test (ma meno accurati).
Eseguirlo in un interprete sul tuo computer / laptop è molto probabilmente più veloce anche per la maggior parte delle persone.


0

Mathematica, 40 byte

NProduct[(1+1/n)^#/(1+#/n),{n,1,∞}]/#&
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.