Implementar la función Polygamma
La función de orden de Polygamma \$m\$, \$\psi^{(m)}(z)\$, es el \$(m + 1)\$th derivada del logaritmo de la función gamma , que también es la \$m\$ª derivada de la función digamma . Tu tarea es tomar un número entero \$m\$y un número real positivo \$z\$y salida \$\psi^{(m)}(z)\$
Definiciones
Para aquellos que no están familiarizados con las funciones anteriores (Gamma, Digamma y Polygamma), aquí hay algunas definiciones diferentes para cada una:
\$\Gamma(z)\$
- La función gamma es una extensión del factorial ( \$x! = 1\cdot2\cdot3\cdots(x-1)\cdot(x)\$) a números reales
- \$\Gamma(z) = \int_{0}^{\infty}x^{z-1}e^{-x}dx\$
- \$\Gamma(n) = (n - 1)! \:,\:\: n \in \mathbb{N}\$
- \$\Gamma(n+1) = n\Gamma(n) \:,\:\: n \in \mathbb{N}\$
\$\psi(z)\$
- La función digamma es la derivada logarítmica de la función gamma
- \$\psi(z) = \frac{d}{dz}\ln(\Gamma(z))\$
- \$\psi(z) = \frac{\Gamma'(z)}{\Gamma(z)}\$
- \$\psi(z + 1) = \psi(z) + \frac{1}{z}\$
\$\psi^{(m)}(z)\$
- La función poligamma de orden \$m\$es el \$m\$th derivada de la función digamma
- \$\psi^{(m)}(z) = \frac{d^m}{dz^m}\psi(z)\$
- \$\psi^{(m)}(z) = \frac{d^{m+1}}{dz^{m+1}}\ln(\Gamma(z))\$
- \$\psi^{(m)}(z+1)= \psi^{(m)}(z) + (-1)^m\frac{m!}{z^{m+1}}\$
Tarea
Debes tomar dos entradas, un número natural \$m\$y un número real positivo \$z\$y salida \$\psi^{(m)}(z)\$. Las entradas y salidas siempre encajarán dentro de los límites numéricos de su idioma, pero su algoritmo debe funcionar teóricamente para todas y cada una de las entradas .
Como la salida suele ser un número real, en lugar de un entero, la salida debe ser correcta al menos en 10 cifras significativas. Los ceros finales se pueden omitir para valores exactos. Por ejemplo, si la salida es un número entero, los decimales finales 0no son obligatorios, pero están permitidos si lo desea.
Esto es código de golf, por lo que gana el código más corto en bytes.
Casos de prueba
Los resultados pueden diferir debido a inexactitudes de punto flotante, se utilizó la biblioteca scipy de Python para generar los valores. Los valores se redondean a 15d.p., a menos que se indique lo contrario.
m, z -> ψ⁽ᵐ⁾(z)
17, 2 -> 1357763223.715975761413574
5, 40 -> 0.0000002493894351
9, 53.59375 -> 0.00000000001201026493
35, 9 -> 469354.958166260155849
46, 5 -> -7745723758939047727202304.000000000000000
7, 1.2222222222222222 -> 1021.084176496877490
28, 6.25 -> -2567975.924144014250487
2, 7.85 -> -0.018426049840992
Esta tabla tiene los valores de \$\psi^{(m)}(z)\$para \$0 \le m \le 9\$y \$1 \le z \le 20\$:
+---+------------------------+---------------------+--------------------+--------------------+--------------------+--------------------+--------------------+--------------------+--------------------+--------------------+--------------------+--------------------+--------------------+--------------------+--------------------+--------------------+--------------------+--------------------+--------------------+--------------------+
| | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
+---+------------------------+---------------------+--------------------+--------------------+--------------------+--------------------+--------------------+--------------------+--------------------+--------------------+--------------------+--------------------+--------------------+--------------------+--------------------+--------------------+--------------------+--------------------+--------------------+--------------------+
| 0 | -0.577215664901533 | 0.422784335098467 | 0.922784335098467 | 1.256117668431800 | 1.506117668431800 | 1.706117668431800 | 1.872784335098467 | 2.015641477955610 | 2.140641477955610 | 2.251752589066721 | 2.351752589066721 | 2.442661679975812 | 2.525995013309145 | 2.602918090232222 | 2.674346661660794 | 2.741013328327460 | 2.803513328327460 | 2.862336857739225 | 2.917892413294781 | 2.970523992242149 |
| 1 | 1.644934066848227 | 0.644934066848227 | 0.394934066848226 | 0.283822955737115 | 0.221322955737115 | 0.181322955737115 | 0.153545177959338 | 0.133137014694031 | 0.117512014694031 | 0.105166335681686 | 0.095166335681686 | 0.086901872871768 | 0.079957428427324 | 0.074040268664010 | 0.068938227847684 | 0.064493783403239 | 0.060587533403239 | 0.057127325790783 | 0.054040906037696 | 0.051270822935203 |
| 2 | -2.404113806319188 | -0.404113806319189 | -0.154113806319189 | -0.080039732245115 | -0.048789732245114 | -0.032789732245115 | -0.023530472985855 | -0.017699569195768 | -0.013793319195768 | -0.011049834970802 | -0.009049834970802 | -0.007547205368999 | -0.006389797961592 | -0.005479465690312 | -0.004750602716552 | -0.004158010123959 | -0.003669728873959 | -0.003262645625435 | -0.002919710097314 | -0.002628122402315 |
| 3 | 6.493939402266829 | 0.493939402266829 | 0.118939402266829 | 0.044865328192755 | 0.021427828192755 | 0.011827828192755 | 0.007198198563125 | 0.004699239795945 | 0.003234396045945 | 0.002319901304290 | 0.001719901304290 | 0.001310093231071 | 0.001020741379219 | 0.000810664701232 | 0.000654479778283 | 0.000535961259764 | 0.000444408525389 | 0.000372570305061 | 0.000315414383708 | 0.000269374221340 |
| 4 | -24.886266123440890 | -0.886266123440879 | -0.136266123440878 | -0.037500691342113 | -0.014063191342113 | -0.006383191342113 | -0.003296771589026 | -0.001868795150638 | -0.001136373275638 | -0.000729931168235 | -0.000489931168235 | -0.000340910050701 | -0.000244459433417 | -0.000179820455575 | -0.000135196191875 | -0.000103591253604 | -0.000080703070010 | -0.000063799959344 | -0.000051098643488 | -0.000041405977726 |
| 5 | 122.081167438133861 | 2.081167438133896 | 0.206167438133897 | 0.041558384635954 | 0.012261509635954 | 0.004581509635954 | 0.002009493175049 | 0.000989510004771 | 0.000531746332896 | 0.000305945162117 | 0.000185945162117 | 0.000118208290511 | 0.000078020533309 | 0.000053159387985 | 0.000037222150950 | 0.000026687171526 | 0.000019534614153 | 0.000014563111016 | 0.000011034967722 | 0.000008484266206 |
| 6 | -726.011479714984489 | -6.011479714984437 | -0.386479714984435 | -0.057261607988551 | -0.013316295488551 | -0.004100295488551 | -0.001528279027645 | -0.000654007738836 | -0.000310684984930 | -0.000160150871077 | -0.000088150871077 | -0.000051203486564 | -0.000031109607963 | -0.000019635233198 | -0.000012804988755 | -0.000008590996985 | -0.000005908787970 | -0.000004154139804 | -0.000002978092040 | -0.000002172607350 |
| 7 | 5060.549875237640663 | 20.549875237639476 | 0.862375237639470 | 0.094199654649073 | 0.017295357774073 | 0.004392957774073 | 0.001392271903016 | 0.000518000614207 | 0.000217593204539 | 0.000100511115987 | 0.000050111115987 | 0.000026599144024 | 0.000014877714841 | 0.000008699205352 | 0.000005284083130 | 0.000003317553637 | 0.000002144087193 | 0.000001421585007 | 0.000000964233099 | 0.000000667475582 |
| 8 | -40400.978398747647589 | -80.978398747634884 | -2.228398747634885 | -0.179930526327158 | -0.026121932577158 | -0.005478092577158 | -0.001477178082416 | -0.000478010895205 | -0.000177603485537 | -0.000073530517936 | -0.000033210517936 | -0.000016110901963 | -0.000008296615840 | -0.000004494456155 | -0.000002542957742 | -0.000001494142013 | -0.000000907408791 | -0.000000567407762 | -0.000000364140247 | -0.000000239189714 |
| 9 | 363240.911422382690944 | 360.911422382626938 | 6.536422382626807 | 0.391017718703625 | 0.044948382766125 | 0.007789470766125 | 0.001788099024012 | 0.000503455497598 | 0.000165497161722 | 0.000061424194120 | 0.000025136194120 | 0.000011145599233 | 0.000005284884641 | 0.000002652620244 | 0.000001398085550 | 0.000000768796112 | 0.000000438758675 | 0.000000258758130 | 0.000000157124373 | 0.000000097937278 |
+---+------------------------+---------------------+--------------------+--------------------+--------------------+--------------------+--------------------+--------------------+--------------------+--------------------+--------------------+--------------------+--------------------+--------------------+--------------------+--------------------+--------------------+--------------------+--------------------+--------------------+
Respuestas
JavaScript (ES7), 68 66 61 59 bytes
Espera (m)(z).
(m,n=m)=>g=z=>n?-n--*g(z):eval("for(k=5e6;k--;)n-=z++**~m")
¡Pruébelo en línea!
Esto se basa en la siguiente representación de la serie ( de Wikipedia ):
$$\psi^{(m)}(z)=(-1)^{m+1}m!\sum_{k=0}^{\infty}\dfrac{1}{(z+k)^{m+1}}$$
Comentado
(m, n = m) => // outer function taking m and saving a copy in n
g = z => // inner recursive function taking z
n ? // if n is not equal to 0:
-n-- // yield -n to invert the sign; decrement n afterwards
* g(z) // multiply by the result of a recursive call
: // else:
eval( // evaluate as JS code:
"for(k = 5e6; k--;)" + // repeat 5 million times:
"n -= z++ ** ~m" // subtract z ** -(m+1) from n; increment z
) // end of eval(), which returns the final value of n
Mathematica, 9 bytes
PolyGamma
Por supuesto, Mathematica tiene una función incorporada para esto.
R , 8 bytes
psigamma
¡Pruébelo en línea!
Toma entradas z,m(prueba el arnés robado de la respuesta de Dominic ).
R tiene una función incorporada como parte de sus Funciones especiales de matemáticas, incluidas varias formas de la función gamma.
Mathematica, 32 bytes (30 caracteres)
Sin ningún Gammaincorporado relacionado, utiliza la fórmula de Bubbler
Sum[#!/(-#2-x)^(#+1),{x,0,∞}]&
¡Pruébelo en línea!
Mathematica, 29 bytes
Sin PolyGamma[z]oPolyGamma[n, z]
Log@Gamma@x~D~{x,#+1}/.x->#2&
¡Pruébelo en línea!
Mathematica, 27 bytes
Con PolyGamma[z](esto es el equivalente a la función digamma, o \$\large\psi^0(z)\$)
PolyGamma@x~D~{x,#}/.x->#2&
¡Pruébelo en línea!
Algunos programas de Mathematica que no usan el PolyGamma[n, z].
05AB1E , 16 15 bytes
₄nÝ+I±mOI!IÉ·<P
-1 byte gracias a @ovs .
La primera entrada es \$z\$, la segunda entrada es \$m\$.
Pruébelo en línea o verifique todos los casos de prueba .
Explicación:
Utiliza el mismo algoritmo que en la respuesta de JavaScript de @Arnauld , así que asegúrate de votarlo.
O para ser más precisos, utiliza el algoritmo:
$$\psi^{(m)}(z)=(m\text{%}2\times2-1)\times m!\times\sum_{k=0}^{1000^2}{(z+k)^{\sim m}}$$
₄ # Push 1000
n # Square it to 1000000
Ý # Pop and push a list in the range [0,1000000]
+ # Add the first (implicit) input-integer `z` to each value
I # Push the second input `m`
± # Take it's bitwise-NOT: -m-1
m # Take each value to the power this `-m-1`
O # Sum all values in the list together
I! # Push the second input `m` again, and take its factorial
IÉ # Push the second input `m` again, and check if it's odd
# (1 if truthy; 0 if falsey)
· # Double that
< # And decrease it by 1
P # And finally take the product of all three values on the stack
# (after which it is output implicitly as result)
NOTA: Si hay pequeñas imprecisiones en los decimales, el ₄n( \$1\text{,}000\text{,}000\$) podría reemplazarse con žm( \$9\text{,}876\text{,}543\text{,}210\$), aunque sería demasiado lento ejecutarlo en TIO en ese caso.
Octava / MATLAB, 4 bytes
@psi
¡Pruébelo en línea!
APL (Dyalog Unicode) 18.0, 20 bytes
+/!⍤⊣÷(-(⍳!9)+⊢)*1+⊣
¡Pruébelo en línea!
-2 bytes gracias a Adám y ngn.
APL (Dyalog Unicode) , 22 bytes
{+/(!⍺)÷(-⍵+⍳1e6)*1+⍺}
¡Pruébelo en línea!
El argumento de la izquierda es \$m\$, el argumento derecho es \$z\$.
Utiliza una ligera modificación de la fórmula utilizada por otras respuestas:
$$ \begin{aligned} \psi^{(m)}(z)&=(-1)^{m+1}m!\sum_{k=0}^{\infty}\dfrac{1}{(z+k)^{m+1}} \\ &\approx\sum_{k=0}^{10^6-1}\dfrac{m!}{(-z-k)^{m+1}} \end{aligned} $$
Cómo funciona
{+/(!⍺)÷(-⍵+⍳1e6)*1+⍺} ⍝ ⍺←m, ⍵←z
-⍵+⍳1e6 ⍝ vector of -(z+0..999999)
( )*1+⍺ ⍝ raise each to the power of 1+m
+/(!⍺)÷ ⍝ divide m! by each of above and sum them
R , 52 51 45 44 bytes
Editar: -1 + 1 bytes gracias a Giuseppe, quien también señaló que ya existe una función R incorporada psigamma, que resuelve la tarea por solo 8 bytes
Edit2: ... y -6 bytes más gracias a Robin Ryder
function(m,z)gamma(M<-m+1)*sum((-z:-1e4)^-M)
¡Pruébelo en línea!
Utiliza la misma fórmula que la respuesta de Arnauld.
Las representaciones en serie como esta son muy adecuadas para R como lenguaje vectorizado de forma nativa.
Cambie 1e4a valores más altos (hasta 9e9sin aumentar el número de bytes) para obtener una precisión progresivamente mayor y un tiempo de ejecución más lento.
Python 3 , 38 bytes
from scipy.special import*
f=polygamma
¡Pruébelo en línea!
Java, 168 148 102 bytes
(m,z)->{double p=1-m%2*2,f=0;long i=m;for(;i>0;)p*=i--;for(;i<1e7;)f-=p*Math.pow(z+i++,~m);return f;};
Explicación
Usé el mismo algoritmo que en la respuesta de JavaScript de @ Arnauld . Por favor vote su respuesta.
Para mayor comodidad, aquí la versión formateada automáticamente:
(m, z) -> {
double p = 1 - m % 2 * 2, f = 0;
long i = m;
for (; i > 0; ) p *= i--;
for (; i < 1e7; ) f -= p * Math.pow(z + i++, ~m);
return f;
};
Código Java tan típico: bastante detallado. Al menos mi versión.
Editar: podría ahorrar 20 bytes gracias a @user
Editar: ahorró aún más bytes gracias a @ceilingcat
Pruébelo en línea
Pyth , 24 bytes
**^_1JhhQ*FhQsm^+deQ_JCG
¡Pruébelo en línea! (el enlace apunta a un código ligeramente diferente que suma 1e5términos en lugar de 1.56e62términos para hacer que el código se pueda ejecutar y evitar errores de desbordamiento)
Explicación
Utiliza el mismo algoritmo que en la respuesta de JavaScript de @ Arnauld , así que asegúrese de votarlo.
**^_1JhhQ*FhQsm^+deQ_JCG
JhhQ : Set J to first input + 1
^_1J : -1 ^ J
* *FhQ : times factorial of first input
* s : times sum of
m : mapping
^+deQ_J : F(d): (d + (second input)) ^ -J
CG : on range(1.56e62)
Scala , 68 bytes
Ahorré 3 bytes y arreglé mi respuesta gracias a Arnauld
Utiliza el algoritmo de la respuesta de Arnauld
m=>z=>(0 to 1<<20 map(z+_ pow ~m)sum)*(m%2*2-1)*(1.0/:(1 to m))(_*_)
¡Pruébelo en línea!