Tengo una pregunta simple que es realmente difícil para Google (además del canónico Lo que todo informático debe saber sobre el papel de aritmética de punto flotante ).
¿Cuándo deberían usarse funciones como log1po en expm1lugar de logy exp? ¿Cuándo no deberían ser utilizados? ¿Cómo difieren las diferentes implementaciones de esas funciones en términos de su uso?
floating-point
Tim
fuente
fuente

log1pse refiere (especialmente cómo se implementa, por lo que no tenemos que adivinar).Respuestas:
Todos sabemos que implica que para , tenemos . Esto significa que si tenemos que evaluar en coma flotante , para puede producir una cancelación catastrófica.exp(x)=∑n=0∞xnn!=1+x+12x2+… |x|≪1 exp(x)≈1+x exp(x)−1 |x|≪1
Esto se puede demostrar fácilmente en python:
Los valores exactos sonexp(10−8)−1exp(10−22)−1=0.000000010000000050000000166666667083333334166666668…=0.000000000000000000000100000000000000000000005000000…
En general, una implementación "precisa" de
expyexpm1debe ser correcta a no más de 1ULP (es decir, una unidad del último lugar). Sin embargo, dado que lograr esta precisión da como resultado un código "lento", a veces hay disponible una implementación rápida y menos precisa. Por ejemplo en CUDA tenemosexpfyexpm1f, dondefsignifica rápido. De acuerdo con la guía de programación CUDA C, aplicación. D elexpftiene un error de 2ULP.Si no le importan los errores en el orden de pocas ULPS, generalmente las implementaciones diferentes de la función exponencial son equivalentes, pero tenga en cuenta que los errores pueden estar ocultos en alguna parte ... (¿Recuerda el error Pentium FDIV ?)
Por lo tanto, está bastante claro queexp(x)−1 x x
expm1debería usarse para calcular para pequeña . Usarlo para general no es dañino, ya que se espera que sea preciso en todo su rango:expm1(En el ejemplo anterior está muy por debajo de 1ULP de , por lo que las tres expresiones devuelven exactamente el mismo número de coma flotante).1 exp(200)
Una discusión similar es válida para las funciones inversaslog(1+x)≈x |x|≪1
logylog1pdesde para .fuente
expm1(x)lugar deexp(x)-1. Por supuesto queexp(x) == exp(x) - 1no se cumple en general.expm1(x)debe ser preciso a 1ULP en todo el rango , pierde progresivamente la precisión de algunos ULP cuando a un desglose completo cuando , donde es máquina-epsilon.exp(x) - 1Para ampliar la diferencia entre
logylog1ppodría ayudar recordar el gráfico si el logaritmo:Si sus datos contienen ceros, entonces probablemente no quiera usarlos,x 0 ln(x) −∞ x 0 ln(x) ln(1e)=−1 ln(1e10)=−10
logya que no están definidos en cero. Y a medida que acerca a , el valor de acerca a . Entonces, si sus valores de están cerca de , entonces el valor de es potencialmente un número negativo grande. Por ejemplo y y así sucesivamente. Esto puede ser útil, pero también puede distorsionar sus datos hacia números negativos grandes, especialmente si su conjunto de datos también contiene números mucho más grandes que cero.Por otro lado, cuando acerca a , el valor de acerca a desde la dirección positiva. Por ejemplo y . Por lo tanto, produce solo valores positivos y elimina el "peligro" de los grandes números negativos. Esto generalmente asegura una distribución más homogénea cuando un conjunto de datos contiene números cercanos a cero.x 0 ln(x+1) 0 ln(1+1e)∼0.31 ln(1+1e10)∼0.000045
log1pEn resumen, si el conjunto de datos es mayor que , generalmente está bien. Pero, si el conjunto de datos tiene números entre y , generalmente es mejor.1 0 10 1
loglog1pfuente