Se trata esencialmente de un debate más profundo sobre la eficacia y la precisión de los distintos métodos.
Reducir el argumento para que esté cerca $1$ :
Fundamentalmente, la mayoría de las respuestas persiguen el mismo objetivo: reducir los argumentos a valores pequeños y utilizar la expansión de Taylor para $\ln(x)$ . Hasta ahora hemos visto 3 enfoques:
1) Factorizar una potencia de 2 y utilizar $\ln(a\cdot2^n)=\ln(a)+n\ln(2)$ .
2) Factorizar una potencia de 10 y utilizar $\ln(a\cdot10^n)=\ln(a)+n\ln(10)$ .
3) Reducir por medio del enraizamiento al cuadrado utilizando $\ln(x)=2\ln(\sqrt x)$ .
Podemos notar que el enraizamiento cuadrado del argumento reduce el argumento mucho más rápido que los otros métodos, que dividen el argumento por una constante repetidamente, ya que $\sqrt x\ll x/10<x/2$ para grandes $x$ . Siendo realistas, si tu entrada no tiene más de, digamos, 1000 dígitos, entonces sólo tienes que hacer la raíz cuadrada unas 10 veces en el peor de los casos. Sin embargo, esto tiene el coste de tener que realizar más cálculos para encontrar la raíz cuadrada, que no son fáciles. Por otro lado, realizar las divisiones es extremadamente fácil. Debido a la naturaleza de cómo escribimos/almacenamos los números, todas las divisiones pueden ser calculadas a la vez simplemente moviendo el punto decimal. A continuación, podemos truncar fácilmente hasta la precisión deseada. Con el enraizamiento cuadrado, el error es más difícil de manejar, y como el registro se multiplica por 2 cada vez, el error absoluto se multiplica por 2 también.
Por supuesto, la elección de escribir el argumento como múltiplo de una potencia de 2 o de una potencia de 10 depende de si lo hace un ordenador o un humano. Es probable que prefiera trabajar en base 10.
También está la cuestión adicional de cuál es nuestra gama de $a$ debe ser. Como queremos que sea lo más cercano a 1, podemos hacer algo de álgebra y ver. Para potencias de 2, queremos $a\in(a_0,2a_0]$ tal que $2a_0-1=1-a_0$ . Si se resuelve esto, se obtiene $a\in[\frac23,\frac43]$ . Para las potencias de 10, queremos $a\in[\frac2{11},\frac{20}{11}]$ .
Utilizando expansiones en serie:
A partir de aquí podría utilizar la expansión estándar de Taylor para el logaritmo natural:
$$\ln(a)=\sum_{k=1}^\infty\frac{(-1)^{k+1}}k(a-1)^k=(a-1)-\frac{(a-1)^2}2+\frac{(a-1)^3}3-\frac{(a-1)^4}4+\mathcal O(a-1)^5$$
sin embargo esto no converge tan rápido como se podría lograr realizando una expansión de Taylor más cercana a $a$ . Lo anterior viene dado por la definición integral del logaritmo natural y la expansión de Taylor del integrando en $1$ :
$$\ln(a)=\int_1^a\frac{\mathrm dt}t=\sum_{k=0}^\infty(-1)^k\int_1^a(t-1)^k~\mathrm dt$$
Pero podemos mejorar esto ampliando en medio de $1$ y $a$ :
\begin{align}\ln(a)=\int_1^a\frac{\mathrm dt}t&=\sum_{k=0}^\infty(-1)^k\left(\frac2{a+1}\right)^{k+1}\int_1^a\left(t-\frac{a+1}2\right)^k~\mathrm dt\\&=\sum_{k=0}^\infty\frac{(-1)^k}{k+1}\left(\frac{a-1}{a+1}\right)^{k+1}\left(1-(-1)^{k+1}\right)\\&=\sum_{k=0}^\infty\frac2{2k+1}\left(\frac{a-1}{a+1}\right)^{2k+1}\end{align}
Para $a$ cerca de $1$ lo anterior tiene un error aproximado de $\mathcal O((a-1)/2)^{2n+1}$ cuando se utiliza $n$ términos. Una derivación algebraica de lo anterior es proporcionada por Wikipedia pero no muestra realmente lo rápido que este converge. Como estamos dos veces más cerca del límite más lejano de la integral, ganamos un dígito binario adicional de precisión por término. Pero como la mitad de los términos desaparecen, esto significa que básicamente podemos calcular el doble de dígitos por término. Este es el método mencionado por Respuesta de Ian .
Aquí es un programa en Ruby que calcula el logaritmo usando series.
Utilizando métodos de búsqueda de raíces:
Mientras que los métodos en serie son realmente agradables y convergen decentemente rápido, Wikipedia proporciona dos métodos más para una evaluación aún más precisa. El primero lo proporciona Eric Towers y supone el cálculo del logaritmo mediante funciones exponenciales. Por supuesto, como el cálculo es barato y la precisión no se ve afectada tanto, recomendaría reducir el argumento para que vuelva a estar cerca de $1$ . Esto significa que $y$ tal y como se define a continuación, se acercará a $0$ permitiendo un cálculo más rápido de la exponencial. Esto también significa que podemos utilizar simplemente $y_0=0$ como nuestra suposición inicial.
$$y=\ln(x)\Rightarrow x=\exp(y)\Rightarrow x-\exp(y)=0$$
En la que podemos aplicar métodos estándar de búsqueda de raíces, como Método de Newton (duplica los dígitos precisos por paso) o Método Halley (triplica los dígitos precisos por paso).
El cálculo de las funciones exponenciales puede realizarse mediante la expansión de Maclaurin:
$$\operatorname{exmp1}(y)=\exp(y)-1=\sum_{n=1}^\infty\frac{y^n}{n!}=y+\frac{y^2}2+\mathcal O(y^3)$$
Desde $y$ está cerca $0$ hay un gran error de punto flotante en el cálculo $\exp(y)$ que tiene un término dominante de $1$ Así que utilizamos $\operatorname{expm1}(y)$ para sortear esto.
También hay que tener en cuenta que como $\Delta y_n\to0$ es más fácil calcular $\exp(\Delta y_n)$ que $\exp(y_{n+1})$ directamente, y utilizar $\exp(y_{n+1})=\exp(\Delta y_n)\exp(y_n)=\exp(y_n)+\exp(y_n)\operatorname{expm1}(\Delta y_n)$ . Esto reduce la exponenciación principal al primer paso, que es trivial ya que $\exp(0)=1$ .
Dejemos que $y_0=0$ y $\operatorname{expy}_0=1$ .
Para el método de Newton, sea $\displaystyle\Delta y_0=x\operatorname{expy}_0-1$ y:
\begin{cases}\Delta y_n=x\operatorname{expy}_n-1,\\\operatorname{expy}_{n+1}=\operatorname{expy}_n+\operatorname{expy}_n\operatorname{expm1}(-\Delta y_n),\\y_{n+1}=y_n+\Delta y_n\end{cases}
Para el método de Halley, dejemos $\displaystyle\Delta y_0=2\cdot\frac{x-\operatorname{expy}_0}{x+\operatorname{expy}_0}$ y:
\begin{cases}\displaystyle\Delta y_n=2\cdot\frac{x-\operatorname{expy}_n}{x+\operatorname{expy}_n},\\\operatorname{expy}_{n+1}=\operatorname{expy}_n+\operatorname{expy}_n\operatorname{expm1}(\Delta y_n),\\y_{n+1}=y_n+\Delta y_n\end{cases}
Aquí es un programa en Ruby que calcula el logaritmo con el método de Newton y aquí es un programa en Ruby que calcula el logaritmo con el método de Halley.
Utilizando el agm:
El media aritmética-geométrica es una poderosa herramienta que se puede utilizar aquí para calcular rápidamente el logaritmo, así como $\pi$ y ciertas integrales. Se define como:
$$a_0=a,b_0=b\\a_{n+1}=\frac{a_n+b_n}2,b_{n+1}=\sqrt{a_nb_n}\\M(a,b)=\lim_{n\to\infty}a_n=\lim_{n\to\infty}b_n$$
Según Wikipedia, esto es tan rápido y barato de calcular que se puede utilizar para calcular la función exponencial utilizando logaritmos más rápido que las series que aproximan la función exponencial. Para conseguir $p$ de precisión, tome una $m$ para que $s=x2^m$ es mayor que $2^{p/2}$ . Podemos entonces calcular el logaritmo natural como:
$$\ln(x)=\lim_{m\to\infty}\frac{\pi x2^{m-2}}{2M(x2^{m-2},1)}-m\ln(2)$$
que es esencialmente un replanteamiento de la tasa de convergencia de $M(1,t)$ como $t\to\infty$ . Para este método, ni siquiera es necesario reducir el argumento. De hecho, ¡podemos aplicarlo directamente a los argumentos grandes!
Sin embargo, este método tiene algunos inconvenientes. El cálculo requiere que calculemos algunas raíces cuadradas en flotadores grandes, pero esto se puede manejar con una clase de flotadores especialmente definida y las funciones respectivas.
Alternativamente, por supuesto, uno podría simplemente reducir el argumento para evitar grandes flotadores como antes.
Aquí es un programa en Ruby que calcula el logaritmo utilizando la media aritmética-geométrica.
4 votos
La etiqueta logaritmo discreto se refiere a un problema de resolución de ecuaciones módulo de un número entero, no al cálculo del logaritmo natural.
4 votos
La serie de Taylor es muy rápida cuando el argumento es cercano a $1$ . ¿Se puede utilizar una identidad de logaritmo para que el argumento que queda en el logaritmo se acerque a $1$ ?
1 votos
100 decimales no es muy grande en el cálculo de precisión arbitraria. Referencia relevante: Fredrik Johansson, "Implementación eficiente de funciones elementales en el rango de precisión media". En 22º Simposio del IEEE sobre Aritmética Informática (ARITH 22) , pp. 83-89. IEEE, 2015. ArXiv . Resumen Describimos una nueva implementación de las funciones trascendentales elementales exp, sin, cos, log y atan para una precisión variable de hasta aproximadamente 4096 bits. En comparación con la biblioteca MPFR, conseguimos una aceleración máxima que va desde un factor 3 para cos hasta 30 para atan.
3 votos
El "gran número" no está bien definido, por favor danos algunos límites aproximados. $e^{230} \approx 10^{100}$ ¿quieres decir más o menos que eso? ¿Y sólo quieres para enteros, o cualquier flotador arbitrario?