A menudo termino en situaciones en las que es necesario verificar si la diferencia obtenida está por encima de la precisión de la máquina. Parece que para este propósito R tiene una variable útil: .Machine$double.eps. Sin embargo, cuando recurro al código fuente R para obtener pautas sobre el uso de este valor, veo múltiples patrones diferentes.
Ejemplos
Aquí hay algunos ejemplos de la statsbiblioteca:
t.test.R
if(stderr < 10 *.Machine$double.eps * abs(mx))
chisq.test.R
if(abs(sum(p)-1) > sqrt(.Machine$double.eps))
integrar.R
rel.tol < max(50*.Machine$double.eps, 0.5e-28)
lm.influence.R
e[abs(e) < 100 * .Machine$double.eps * median(abs(e))] <- 0
princomp.R
if (any(ev[neg] < - 9 * .Machine$double.eps * ev[1L]))
etc.
Preguntas
- ¿Cómo entender el razonamiento detrás de todas esas diferentes
10 *,100 *,50 *ysqrt()modificadores? - ¿Existen pautas sobre el uso
.Machine$double.epspara ajustar las diferencias debido a problemas de precisión?
r
floating-point
rounding
precision
Karolis Koncevičius
fuente
fuente

double.eps. Si está realizando varias operaciones en un número de coma flotante, entonces su tolerancia a errores también debería ajustarse. Es por eso que all.equal te da unatolerancediscusión.Respuestas:
La precisión de la máquina
doubledepende de su valor actual..Machine$double.epsproporciona la precisión cuando los valores son 1. Puede usar la función CnextAfterpara obtener la precisión de la máquina para otros valores.Agregar valor
aa valorbno cambiarábcuandoasea la<=mitad de la precisión de su máquina. Verificando si la diferencia es más pequeña que con la precisión de la máquina<. Los modificadores podrían considerar casos típicos con qué frecuencia una adición no mostró un cambio.En R, la precisión de la máquina se puede estimar con:
Cada
doublevalor representa un rango. Para una simple suma, el rango del resultado depende del reange de cada sumando y también del rango de su suma.Para mayor precisión se
Rmpfrpodría utilizar.En caso de que pudiera convertirse a entero,
gmppodría usarse (lo que está en Rmpfr).fuente
Definición de una máquina.eps: es el valor más bajo
epspara el que1+epsno1Como regla general (suponiendo una representación de punto flotante con base 2):
Esto
epshace la diferencia para el rango 1 .. 2,para el rango 2 .. 4 la precisión es
2*epsy así sucesivamente.
Desafortunadamente, no hay una buena regla general aquí. Está completamente determinado por las necesidades de su programa.
En R tenemos all.equal como una forma integrada para probar la igualdad aproximada. Entonces podrías usar algo como
(x<y) | all.equal(x,y)Google simulacro tiene una serie de comparadores de punto flotante para comparaciones de doble precisión, incluyendo
DoubleEqyDoubleNear. Puede usarlos en un comparador de matrices como este:Actualizar:
Las recetas numéricas proporcionan una derivación para demostrar que usar un cociente de diferencia unilateral
sqrtes una buena opción de tamaño de paso para aproximaciones de derivadas de diferencias finitas.El sitio del artículo de Wikipedia Numerical Recipes, 3ra edición, Sección 5.7, que está en las páginas 229-230 (hay un número limitado de visitas a la página en http://www.nrbook.com/empanel/ ).
Esta aritmética de coma flotante IEEE es una limitación bien conocida de la aritmética informática y se discute en varios lugares:
.
dplyr::near()es otra opción para probar si dos vectores de números de coma flotante son iguales.La función tiene un parámetro de tolerancia incorporado:
tol = .Machine$double.eps^0.5que se puede ajustar. El parámetro predeterminado es el mismo que el predeterminado paraall.equal().fuente
all.equal()tiene su propia suposición como tolerancia predeterminadasqrt(double.eps): ¿por qué es la predeterminada? ¿Es una buena regla general usarsqrt()?stats::fuente R , y 2) cuáles son las pautas; La respuesta es bastante delgada. La única oración aplicable parece ser la referencia de "Recetas Numéricas" acerca de que sqrt () es un buen valor predeterminado, lo cual es realmente correcto, creo. O tal vez me estoy perdiendo algo aquí.