Função Pi inversa


17

A função Pi é uma extensão do fatorial sobre os reais (ou mesmo números complexos). Para números inteiros n , Π (n) = n! , mas para obter uma definição sobre os reais, definimos-a usando uma integral:

Pi (z) = integral t de 0 ao infinito e ^ -tt ^ z dt

Neste desafio, vamos inverter a Π função.

Dado um número real z ≥ 1 , encontre x positivo de modo que Π (x) = z . Sua resposta deve ser precisa por pelo menos 5 dígitos decimais.


Exemplos:

120 -> 5.0000
10 -> 3.39008
3.14 -> 2.44815
2017 -> 6.53847
1.5 -> 1.66277

4
Observe que com mais frequência as pessoas usam a função Gama (Γ). Π (x) = Γ (x + 1) . Mas IMO Γ é uma abominação deslocada e Π é a verdadeira extensão do fatorial.
orlp

11
Wellp, que a expansão série é o suficiente para me assustar ... i.imgur.com/ttgzDSJ.gif
Magia Octopus Urna

11
Todos os exemplos que você fornece também têm outras soluções, por exemplo 120 -> -0.991706. Isso ocorre porque Π (x) vai para o infinito enquanto x vai para -1 a partir da direita. Talvez você queira insistir que x> 0 também.
Greg Martin

@GregMartin Adicionado também.
orlp

11
Existem algumas razões para preferir a versão alterada, apesar de parecer pouco natural. Veja, por exemplo, esta resposta no MathOverflow e outras da página.
Ruslan

Respostas:


8

Mathematica, 17 15 27 bytes

FindInstance[#==x!&&x>0,x]&

Saída parece {{x -> n}}, onde nestá a solução, que pode não ser permitida.


7

Pitão, 4 bytes

.I.!

Um programa que recebe a entrada de um número e imprime o resultado.

Suíte de teste

Como funciona

.I.!    Program. Input: Q
.I.!GQ  Implicit variable fill
.I      Find x such that:
  .!G    gamma(x+1)
     Q   == Q
        Implicitly print

5

MATL , 13 bytes

1`1e-5+tQYgG<

Isso usa pesquisa linear nas etapas de 1e-5início em 1. Por isso, é terrivelmente lento e atinge o tempo limite no compilador online.

Para testá-lo, o link a seguir substitui o 1e-5requisito de precisão por1e-2 . Experimente online!

Explicação

1        % Push 1 (initial value)
`        % Do...while
  1e-5   %   Push 1e-5
  +      %   Add
  t      %   Duplicate
  QYg    %   Pi function (increase by 1, apply gamma function)
  G<     %   Is it less than the input? If so: next iteration
         % End (implicit)
         % Display (implicit)

3

GeoGebra , 25 bytes

NSolve[Gamma(x+1)=A1,x=1]

Entrou na entrada do CAS e espera a entrada de um número na célula da planilha A1 . Retorna uma matriz de um elemento do formulário {x = <result>}.

Aqui está um gif da execução:

Execução de progrma

Como funciona

Numeralmente Solvea seguinte equação :, Gamma(x+1)=A1com valor inicial x=1.


É garantido retornar um número positivo e funciona para 1,5, que quebrou várias respostas?
Pavel

@ Pavel, posso confirmar que funciona 1.5. Não consegui descobrir qual algoritmo o GeoGebra usa para resolver numéricos, mas o valor inicial de x=1deu respostas puramente positivas para todos os valores que tentei.
TheBikingViking 29/01

2

MATLAB, 59 bytes

@(x)fminsearch(@(t)(gamma(t+1)-x)^2,1,optimset('TolF',eps))

Essa é uma função anônima que encontra o minimizador da diferença quadrada entre a função Pi e sua entrada, começando em 1 , com tolerância muito pequena (fornecida por eps) para obter a precisão desejada.

Casos de teste (executados no Matlab R2015b):

>> @(x)fminsearch(@(t)(gamma(t+1)-x)^2,1,optimset('TolF',eps))
ans = 
    @(x)fminsearch(@(t)(gamma(t+1)-x)^2,1,optimset('TolF',eps))
>> f = ans; format long; f(120), f(10), f(3.14), f(2017)
ans =
   5.000000000000008
ans =
   3.390077650547032
ans =
   2.448151165246967
ans =
   6.538472664321318

Você pode experimentá-lo on-line no Octave, mas infelizmente alguns dos resultados não têm a precisão necessária.


2

J, 86 33 bytes

((]-(-~^.@!)%[:^.@!D.1])^:_>:)@^.

Usa o método de Newton com o log Pi para evitar o estouro.

Esta é a versão anterior que calcula o registro Gamma usando a aproximação de Stirling. O tamanho da etapa (1e3) e o número de termos no log Gamma (3) podem ser aumentados para uma precisão possivelmente mais alta ao custo do desempenho.

3 :'(-(k-~g)%%&1e3(g=:((%~12 _360 1260 p.&:%*:)+-+^~-&^.%:@%&2p1)@>:)D:1])^:_>:k=:^.y'

Outra versão que calcula os termos do coeficiente em tempo real

3 :'(-((-^.y)+g)%%&1e3(g=:((%~(((%1-^@-)t:%]*<:)+:>:i.3)p.%@*:)+(*^.)-]+-:@^.@%&2p1)@>:)D:1])^:_>:^.y'

Experimente online! e para ver os termos convergirem .

Explicação

((]-(-~^.@!)%[:^.@!D.1])^:_>:)@^.  Input: float y
(                            )@^.  Operate on log(y)
                           >:        Increment, the initial guess is log(y)+1
 (                     )^:_          Repeat until convergence starting with x = log(y)+1
                      ]                Get x
               ^.@!                    The log Pi verb
             [:    D.1                 Approximate its first derivative at x
       ^.@!                            Apply log Pi to x
     -~                                Subtract log(y) from it
            %                          Divide it by the derivative
  ]-                                   Subtract it from x and use as next value of x

2

Mathematica, 21 bytes

FindRoot[#-x!,{x,1}]&

FindRoot aplica o método de Newton internamente quando há um valor inicial.

Os dois métodos abaixo aplicam o método de Newton diretamente.

Alternativa usando o FixedPoint 45 bytes

FixedPoint[#-(#!-y)/Gamma'[#+1]&,Log[y=#]+1]&

Uma implementação mais precisa do método de Newton para resolver isso, já que o Mathematica pode calcular a derivada diretamente, em vez de aproximar.

O uso de regras para substituir repetidamente seria mais curto, mas há um limite (65536) para quantas iterações podem ser executadas que podem ser atingidas, embora FixedPointnão tenham um limite.

Alternativa usando regras, 38 bytes

Log[y=#]+1//.x_->x-(x!-y)/Gamma'[x+1]&

Imagem


1

Geléia , 34 bytes

Ḋ!Æl_®
ȷİ‘×;µ!ÆlI÷I÷@Ç_@ḊḢ
Æl©‘ÇÐĿ

Experimente online! ou Exibir os valores intermediários à medida que eles convergem .

Uma implementação da combinação de J do método de Newton e aproximação de derivada (método secante) para calcular o inverso de Π ( n ).

Ele resolve o inverso do log ( Π ( n )) para evitar o estouro.

Começa com um palpite inicial x 0 = y +1 onde y = log ( Π ( n )). Em seguida, itera até a convergência usando x n +1 = x n - (log ( Π ( x n )) - y ) / (log (( Π (1.001 * x n )) - log ( Π ( x n ))) / (0,001 * x n )).


3
Eu recebo um erro na entrada1.5
Luis Mendo

@LuisMendo Uau, isso é uma boa pegada! Isso ocorre porque um dos valores intermediários é ~ 65807, que é um valor enorme após a aplicação de gama e o Python exceder. O mesmo ocorre em J, uma vez que depende da mesma computação.
milhas

1

PARI / GP, 30 bytes

x->solve(t=1,x+1,gamma(t+1)-x)

Encontra solução entre 1e x+1. Infelizmente, xnão é grande o suficiente como limite superior para entrada como 1.5.


1

Mathematica, 26 bytes

Mais uma solução Mathematica!

A solução de equações sempre pode ser transformada em um problema de minimização.

NArgMin[{(#-x!)^2,x>0},x]&

Encontra o argumento que minimiza a diferença entre os lados esquerdo e direito da equação.

O uso do NArgMin em vez do NMinimize força a saída a ser apenas o resultado desejado, em vez da saída detalhada baseada em regras, usual (e salva um byte!)


0

C com libm, 111

Atualização - corrigida para a entrada 1.5.

f(double *z){double u=2**z,l=0,g=u,p=0;for(;log(fabs(g-p))>-14;)p=g,g=(u+l)/2,u=tgamma(g+1)>*z?g:(l=g,u);*z=g;}

gamma(x+1)é uma função monotonicamente crescente no intervalo em questão; ela é apenas uma pesquisa binária até que a diferença entre valores sucessivos seja pequena. O limite inferior inicial é 0e o limite superior inicial é 2*x.

A entrada e a saída são feitas através de um ponteiro para uma passagem dupla para a função.

Tenho certeza de que isso pode ser jogado mais fundo - em particular, acho que não preciso de quatro duplas locais, mas até agora não estou vendo uma maneira fácil de reduzir isso.

Experimente online - Cria (vincula-se à libm) e roda em um script bash.

Ligeiramente não-destruído:

f(double *z){
    double u=2**z,l=0,g=u,p=0;
    for(;log(fabs(g-p))>-14;){
        p=g;
        g=(u+l)/2;
        u=tgamma(g+1)>*z?g:(l=g,u);*z=g;
    }
}
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.