2011-10-05 14 views
7

A previous post mi ha spinto a postare questa domanda. Sembrerebbe come una best-practice per riassegnare == a isTRUE(all.equal()) (e != a !isTRUE(all.equal()). Mi chiedo se gli altri fanno in pratica? Ho appena realizzato che io uso == e != di fare uguaglianza numerica per tutta la mia base di codice. La mia prima reazione era che ho bisogno di fare un full-scrub e convertirlo in all.equal. Ma in realtà, ogni volta che uso == e != voglio testare l'uguaglianza (indipendentemente dal tipo di dati) .Infatti, non sono sicuro di cosa verrebbero testate queste operazioni per altro che l'uguaglianza, sono sicuro che mi manca qualche concetto qui. Qualcuno può illuminarmi? L'unico argomento che vedo contro questo approccio è che in alcuni casi due numeri non identici sembreranno identici a causa della tolleranza di all.equal. Ma ci viene detto che due numeri che sono in effetti identici potrebbero non passare identical() a causa di come sono memorizzati in memoria. Quindi, in realtà, qual è il punto di non default di all.equal?Riassegnate == e! = A isTRUE (all.equal())?

+0

Che sembrava una cosa così strana da fare, poi ho letto la nota nella pagina di aiuto di confronto: "Non usare == e = per i test, come ad esempio nel caso di espressioni, in cui è necessario ottenere un! singolo VERO o FALSO. A meno che tu non sia assolutamente sicuro che non possa accadere nulla di insolito, dovresti invece usare la stessa funzione. " Quindi forse non è un'idea così assurda. –

+3

Devo dire di no, non dovresti. Usa 'identico', invece, e mantieni' == 'in giro per i confronti vettorizzati durante il subsetting. – joran

+3

Se inizi a sovraccaricare gli operatori comuni, il tuo codice sarà seriamente non portatile. Molto meglio imparare cosa fa ogni operatore o funzione e utilizzare lo strumento giusto per il lavoro giusto. –

risposta

7

Come ha fatto @joran, si verificheranno problemi in virgola mobile con == e != praticamente in qualsiasi altra lingua. Un aspetto importante di essi in R è la parte di vettorizzazione.

Sarebbe molto meglio definire una nuova funzione almostEqual, fuzzyEqual o simile. È un peccato che non ci sia una tale funzione di base. all.equal non è molto efficiente poiché gestisce tutti i tipi di oggetti e restituisce una stringa descrivendo la differenza quando principalmente si desidera solo TRUE o FALSE.

Ecco un esempio di tale funzione. È vettorizzato come ==.

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 

... Si tratta di circa 2 volte più veloce di all.equal per i valori scalari, e molto più veloce con i vettori.

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 - dopo alcuni test penso che ci sia un bug in questa funzione. Considerare: matrixa = round (matrice (rnorm (9), nrow = 3, ncol = 3), 6) matrixb = matrixa - .001 quasiEqual (matrice, matrice, tolleranza = .001) – SFun28

+0

Anche questo a volte produce FALSE: quasiEqual (matrixa, matrixb, tolleranza = .01) – SFun28

+0

@ SFun28 - Penso che il codice sia corretto. Prova 'all.equal' invece e ottieni anche non-TRUE. È perché è una tolleranza RELATIVA.'rnorm' può dare numeri grandi (3.5) o piccoli (0.0003), ma il tuo errore che aggiungi a matrixb è sempre' 0.001'. Prova invece 'matrixb <- matrixa * 1.001'. – Tommy

Problemi correlati