2011-10-05 6 views
7

A previous post me llevó a publicar esta pregunta. Parecería una buena práctica reasignar == a isTRUE(all.equal()) (y != a !isTRUE(all.equal()). Me pregunto si otros lo hacen en la práctica? Me acabo de dar cuenta de que uso == y != para hacer igualdad numérica en mi código base. Mi primera reacción fue que necesito hacer un scrub completo y convertirme a all.equal. Pero de hecho, cada vez que uso == y != quiero probar la igualdad (independientemente del tipo de datos). De hecho, no estoy seguro de qué probarían estas operaciones para otro que no sea la igualdad. Estoy seguro de que me falta algún concepto aquí. ¿Puede alguien aclararme? El único argumento que veo en contra de este enfoque es que en algunos casos dos números no idénticos parecerán ser idénticos debido a la tolerancia de all.equal. Pero nos dicen que dos números que son de hecho idénticos podrían no pasar identical() debido a cómo están almacenados en la memoria. Entonces, ¿cuál es el punto de no incumplir de manera predeterminada con all.equal?¿Has reasignado == y! = A isTRUE (all.equal())?

+0

Eso parecía una cosa tan extraña que hacer, entonces me leyó la nota en la página de ayuda Comparación: "No usar == y = para las pruebas, como en el caso de las expresiones, en el que debe tener una! solo VERDADERO o FALSO. A menos que esté absolutamente seguro de que no puede pasar nada inusual, debe usar la función idéntica en su lugar ". Entonces tal vez no sea una idea tan absurda. –

+3

Voy a decir que no, no deberías. Use 'idéntico' en su lugar, y mantenga '==' para las comparaciones vectorizadas al subconjunto. – joran

+3

Si comienza a sobrecargar operadores comunes, su código será seriamente no portátil. Es mucho mejor aprender qué hace cada operador o función y usar la herramienta adecuada para el trabajo correcto. –

Respuesta

7

Como aludió a @joran, se encontrará con problemas de punto flotante con == y != en casi cualquier otro idioma también. Un aspecto importante de ellos en R es la parte de vectorización.

Sería mucho mejor definir una nueva función almostEqual, fuzzyEqual o similar. Es desafortunado que no exista tal función base. all.equal no es muy eficiente, ya que maneja todo tipo de objetos y devuelve una cadena que describe la diferencia cuando en su mayoría solo desea TRUE o FALSE.

Aquí hay un ejemplo de dicha función. Se ha vectorizado como ==.

almostEqual <- function(x, y, tolerance=1e-8) { 
    diff <- abs(x - y) 
    mag <- pmax(abs(x), abs(y)) 
    ifelse(mag > tolerance, diff/mag <= tolerance, diff <= tolerance) 
} 

almostEqual(1, c(1+1e-8, 1+2e-8)) # [1] TRUE FALSE 

... que es de alrededor de 2 veces más rápido que all.equal para valores escalares, y mucho más rápido con vectores.

x <- 1 
y <- 1+1e-8 
system.time(for(i in 1:1e4) almostEqual(x, y)) # 0.44 seconds 
system.time(for(i in 1:1e4) all.equal(x, y)) # 0.93 seconds 
+0

Tommy - después de algunas pruebas creo que hay un error en esta función. Considere: matrixa = round (matriz (rnorm (9), nrow = 3, ncol = 3), 6) matrixb = matrixa - .001 almostEqual (matrixa, matrixb, tolerance = .001) – SFun28

+0

Incluso esto produce FALSE algunas veces: almostEqual (matrixa, matrixb, tolerance = .01) – SFun28

+0

@ SFun28 - Creo que el código es correcto. Pruebe 'all.equal' en su lugar y también no es VERDADERO. Es porque es una tolerancia RELATIVA.'rnorm' puede dar números grandes (3.5) o pequeños (0.0003), pero el error que agregue a matrixb siempre es' 0.001'. Pruebe con 'matrixb <- matrixa * 1.001' en su lugar. – Tommy

Cuestiones relacionadas