Me gustaría saber si existe una forma alternativa y explícita (no iterativa) del sinc
que se comporta de forma numéricamente estable para todos los números reales. La definición que conozco es:
$$\texttt{sinc}(a) = \dfrac{\sin(a)}{a}$$
Sin embargo, aunque esta función está bien definida en todas partes (incluso a 0) Esta función presenta problemas cuando se implementa en el código y se evalúa en 0. Me gustaría saber si hay una forma alternativa que implique funciones simples que eviten la posible división por 0 cuando intentemos implementar esto es código.
Algunos paquetes de programación (como numpy en python) proporcionan un sinc
para evitar este problema. Pero me gustaría saber en general si hay una forma mejor de implementarlo en un lenguaje arbitrario sin recurrir a algún if
declaración. Por ejemplo, numpy
simplemente comprueba si a=0
. Si lo es, entonces sustituye a a
con algún valor pequeño $\neq 0$ . Específicamente:
def sinc(x):
y = pi * where(x == 0, 1.0e-20, x)
return sin(y)/y
EDITAR
Como señala Sangchul Lee, se podría considerar la forma de la serie, pero esa representación se romperá para grandes $a$ . Así que la forma de la serie es esencialmente empujar el problema en otro lugar (desde un punto de vista numérico). Además, podría considerar la posibilidad de cambiar entre las dos formas dependiendo de si $a$ es pequeño, pero eso es introducir su propia if
y me gustaría evitar una solución a trozos.
Nota: No tengo ni idea de qué etiquetas utilizar aquí. Así que, por favor, actualice las etiquetas a lo que considere apropiado.
0 votos
¿Existe la posibilidad de utilizar la siguiente ampliación de serie? $$\operatorname{sinc}(a) = \sum_{n=0}^{\infty} \frac{(-1)^n}{(2n+1)!} a^{2n} $$ Esta fórmula funciona especialmente bien cuando $a$ está cerca de cero.
0 votos
Esto no funcionará bien numéricamente. Esto empuja el problema a otro lugar. Específicamente, mientras que su fórmula funcionará bien alrededor de 0, se romperá para grandes $a$ . Así que no es realmente una forma general que sea numéricamente estable
1 votos
Por lo que sé, muchas funciones especiales se implementan de manera fragmentada para lograr la estabilidad numérica para un amplio rango de parámetros, así que supongo que no es malo adoptar la misma estrategia aquí. Por ejemplo, se puede utilizar la fórmula anterior cuando $a$ está dentro de un determinado umbral y, a continuación, utilizar $\sin(a)/a$ de lo contrario.
0 votos
El problema es cuando se trata de la diferenciación. Me gustaría usar esto en un paquete de autodiferenciación, y si tengo una forma a trozos, entonces tengo que insertar un montón de interruptores desagradables, particularmente con derivadas más altas.
0 votos
Si tengo que hacerlo, que así sea. Pero si hay una representación continua agradable y numéricamente estable que pueda utilizar, lo preferiría.
1 votos
Ya veo, eso puede ser un gran problema. Para ser honesto, parece lo mejor si el paquete le permite designar derivados superiores de $\operatorname{sinc}$ para que pueda proporcionar sus propias implementaciones de derivados superiores. O, si se garantiza que el argumento estará acotado dentro de cierto rango, supongo que la siguiente fórmula $$ \operatorname{sinc}(x) = \prod_{k=1}^{\infty} \cos\left(\frac{x}{2^k}\right) $$ también puede ser útil.
0 votos
Si le preocupan las derivadas simbólicas, puede utilizar la representación hipergeométrica $\sin(z)/z = {}_{0}F_{1}(\tfrac{3}{2}, -\tfrac{1}{4}z^2)$
0 votos
Otra opción puede ser utilizar la función esférica de Bessel si está disponible: $\mathrm{sinc}(x)=j_0(x)$
0 votos
@SangchulLee tiene razón, la ramificación es la forma correcta de tener una evaluación rápida y estable para una amplia variedad de parámetros. Si la ramificación rompe la autodiferenciación, es un problema del paquete auto diff.