Função Gamma Golf


17

Dado um número real tem (-10^9,13)(não incluindo -10^9ou 13) como entrada, saída Γ(t), também conhecida como função Gamma , que é definida da seguinte forma:

definição de função gama

Você não pode usar uma função Gamma interna para resolver esta tarefa, nem funções de integração numérica ou simbólica internas. Sua saída deve ter precisão de 6 dígitos significativos ou dentro 10^-6do valor real, o que for menos restritivo para o valor especificado. A função Gamma interna do Python será usada para determinar o valor real. Você pode assumir que Γ(t)está definido - ou seja, té um número real positivo ou um número real negativo não inteiro - e isso |Γ(t)| ≤ 10^9. Aqui está um programa de referência que você pode usar para obter os valores reais, usando a função Gamma interna do Python.

Exemplos

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

Regras

  • Isso é , então a resposta mais curta (em bytes) vence.
  • As brechas padrão são proibidas.
  • A entrada e a saída podem ser executadas da maneira que for considerada padrão para o seu idioma.
  • Você pode escrever um programa completo, uma função ou qualquer coisa que seja normalmente considerada uma resposta válida para o seu idioma.

Entre os melhores

O snippet de pilha na parte inferior desta postagem gera o cabeçalho das respostas a) como uma lista da solução mais curta por idioma eb) como um cabeçalho geral.

Para garantir que sua resposta seja exibida, inicie-a com um título, usando o seguinte modelo de remarcação:

## Language Name, N bytes

onde Nestá o tamanho do seu envio. Se você melhorar sua pontuação, poderá manter as pontuações antigas no título, identificando-as. Por exemplo:

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

Se você quiser incluir vários números em seu cabeçalho (por exemplo, porque sua pontuação é a soma de dois arquivos ou deseja listar as penalidades de sinalizador de intérprete separadamente), verifique se a pontuação real é o último número no cabeçalho:

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

Você também pode transformar o nome do idioma em um link que será exibido no snippet:

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


11
Por favor, forneça limites explícitos para t tal que | gamma (t) | <10 ^ 9
flawr

O link não é uma implementação de referência ...
sergiol

@sergiol Reformulado
Mego

Respostas:


2

Pitão, 21 bytes

Como na minha resposta do TI-BASIC, não pude testar isso com as iterações completas de 8 ^ 10, mas tudo parece bom em casos menores.

cu*Gc^hc1HQhcQHS^8T1Q

Explicação:

                            [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

Experimente aqui com 2000 iterações em vez de 8 ^ 10.


10

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;};

Eu não gastei muito tempo com isso. Eu apenas olhei para uma aproximação que parecia a mais fácil de implementar (na forma de bytes). Levará algum tempo para calcular o valor (já que o loop ultrapassa todos os números inteiros positivos), mas a limitação de tempo não está especificada no desafio. É função anônima (lambda), que leva qualquer argumento (conversível para Tonde pow(double, T)e operator/(T,int)pode ser chamado) e retorna double.

Ungolfed with use

#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 Claro que é! Obrigado.
Zereges

Então, qual valor você obtém para -10 ^ 9 e para 10 ^ 9? Quero primeiro saber como suas coisas funcionam antes de você receber meu voto positivo.
flawr

O compilador da Microsoft @Mego não precisa de nenhum desses itens.
Zereges

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

@flawr O programa de mina gera 0 para gamma(-10e9)mas OP afirmou que somente parâmetros para os quais a função gama está definida podem ser considerados. gamma(10e9)retornos inf, enquanto Python embutido no Gamma função será usada para determinar o valor real dizOverflowError: math range error
Zereges

7

Tamanho 0.12 , 35 34 25 bytes

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

Isso pára com um erro (ao tentar dividir por 0), mas isso é permitido conforme o consenso do Meta . Adicione um .no final para um programa que para normalmente. Tente todos os casos de teste de uma só vez. (O loop itera apenas 1e4 vezes, para terminar mais cedo ou mais tarde.)

Explicação

Zereges usou uma das alternativas, infinitas definições de produtos . Como se vê, o outro é muito mais viável de implementar em Minkolang.

Formulação alternativa de Euler da função gama

Este é um limite no que ndiz respeito ao infinito, o que significa que eu posso calcular ambos n!e à (t+n)medida que avançamos. Então eu retiro 1/t(porque 0!=1) e n^tporque esse não pode ser calculado sequencialmente sem conhecer o valor final de n. Por acaso, como né o limite, posso usá-lo duas vezes. Uma vez como um fator no cálculo e uma vez como o número de vezes para executar o loop.

Um produto infinito seqüencial precisa começar com algo, geralmente 1. Nesse caso, é n^t/t. No corpo do loop, eu calculo k/(t+k)e multiplico isso pelo produto até o momento. No final, todo o produto foi calculado e produzido. Isso é essencialmente o que meu programa faz, com nalto o suficiente para que a resposta seja precisa o suficiente.

versão explodida do produto 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

Como não há ., ele se volta e recomeça. No entanto, nagora produz -1porque a entrada está vazia, o que eventualmente leva à tentativa de dividir por 0, o que interrompe o programa.


5

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

Isso cria uma função lambda sem nome que aceita um número real e retorna um número real. Ele usa a aproximação do Spounge para calcular 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

Muito, muito golfe tarde, mas 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)))deve funcionar para 137 bytes (pelo menos em Julia 0,6)
Mr. Xcoder

3

Japonês, 45 bytes

Japt é uma versão abreviada do Ja vaScri pt . Intérprete

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

Obviamente, 1e9 = 1.000.000.000 de iterações leva uma eternidade; portanto, para testar, tente substituir o 9por um 6. (1e6 é preciso até ~ 5 números significativos. Usar 1e8 em uma entrada de 12é suficiente para obter os seis primeiros.)

Resultados do caso de teste: (usando precisão 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...

Como funciona

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

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

Isso usa o mesmo algoritmo que Zereges.

Advertência: Na verdade, eu não testei isso com as iterações 1e9 completas; com base no tempo gasto para valores menores, espero que o tempo de execução seja da ordem de meses . No entanto, parece convergir e não deve haver problemas com erros de arredondamento. A TI armazena números como números decimais com 14 dígitos de precisão.


Você não testou ?!
TanMath

11
@ TanMath eu precisaria, mas preciso da minha calculadora para um exame final no próximo mês.
lirtosiast

3

Python 3, 74 68 78 73 bytes

Obrigado @Mego e @xnor

Esta é uma tradução da resposta em C ++ de Zereges. Basicamente, esta é uma definição alternativa da função gama, portanto, mais precisa (e o melhor é que usa menos bytes!)

Sinto muito por todos os erros!

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

11
O +1intervalo não importa quando você está lidando com bilhões. Além disso, você deve especificar que esse é o Python 3 - você precisaria from __future__ import divisionde divisão flutuante e alguns terabytes de RAM para lidar com o fato de rangeretornar uma lista no Python 2. Além disso, você pode substituir 1.0s por 1se afastar 4 bytes.
Mego

2
@ TanMath: ^é xor, você não quis dizer **exponenciação?
jermenkoo

3
int(1e9)é justo 10**9e você não precisa de parênteses (1+1/i)**z.
Xnor

3

Python, 348 448 407 390 389 bytes

Agradecimentos especiais a @Mego!

Um 448 riscado ainda é (quase) ainda um 448! : p

Isso é baseado na aproximação de Lanzcos. Golfed daqui

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

11
Golf sua submissão removendo, no mínimo, os espaços em branco (os espaços antes e depois de - = e dentro, import *por exemplo) e usando um nome de função de um caractere. Observe também que você só precisa dar suporte à entrada real.
lirtosiast

@ThomasKwa eu o editei. Minha versão original não funcionou, aqui está uma mais nova.
TanMath

@Mego editado ...
TanMath 15/11

Isso causa um erro de recursão - remova o z-=1;na primeira linha de gammapara corrigi-lo. Você também deve renomear gammapara gpara bytes salvos e para evitar conflitos de nomes com cmath.gamma. Solte também os zeros iniciais estranhos.
Mego

1

Julia, 41 bytes

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

Esta é uma tradução da resposta C ++ de Zereges. Enquanto minha outra resposta de Julia termina instantaneamente, isso é bastante lento. Ele calcula os casos de teste em alguns segundos, cada um no meu computador.

Ungolfed:

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

1

Prolog, 114 bytes

Esta é uma tradução da resposta 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),!.

Experimente online aqui
Execute-o com uma consulta no formulário:

p(12).

Executá-lo com recursões 1e9 leva cerca de 15 minutos.
Se você diminuir para 1e6, leva cerca de 1 segundo, o que facilita o teste (mas menos preciso).
A execução em um intérprete no seu computador / laptop é provavelmente mais rápida para a maioria das pessoas.


0

Mathematica, 40 bytes

NProduct[(1+1/n)^#/(1+#/n),{n,1,∞}]/#&
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.