2011-10-05 5 views
7

A previous post skłonił mnie do opublikowania tego pytania. Wydaje się, że najlepszą praktyką jest ponowne przypisanie == do isTRUE(all.equal()) (i != do !isTRUE(all.equal()). Zastanawiam się, czy inni robią to w praktyce? Właśnie sobie sprawę, że używam == i != do równości numerycznej całej mojej bazy kodowej. Moja pierwsza reakcja było to, że muszę wykonać peeling i przekonwertować do all.equal.Ale faktycznie za każdym razem używać == i != Chcę przetestować równości (bez względu na typ danych) .W rzeczywistości nie jestem pewien, co te operacje będą testować dla innych niż równości Jestem pewien, że brakuje mi tutaj pewnej koncepcji: czy ktoś może mnie oświecić? Jedynym argumentem, jaki widzę przeciwko temu podejściu jest to, że w niektórych przypadkach dwie nieidentyczne liczby wydają się identyczne z powodu tolerancji all.equal. Ale powiedziano nam, że dwie liczby, które w rzeczywistości są identyczne, mogą nie przejść identical() ze względu na sposób ich przechowywania w pamięci. Więc o co właściwie chodzi, aby nie spłacać all.equal?Czy ponownie przypisujesz == i! = Do isTRUE (all.equal())?

+0

To wydawało się być dziwną rzeczą, po czym przeczytałem notatkę na stronie pomocy Porównanie: "Nie używaj == i! = Do testów, takich jak w wyrażeniach, gdzie musisz uzyskać pojedyncze PRAWDA lub FAŁSZ Jeśli nie masz absolutnej pewności, że nie może się zdarzyć nic niezwykłego, powinieneś użyć identycznej funkcji. " Więc może to nie jest taki absurdalny pomysł. –

+3

Powiem "nie", nie powinieneś. Zamiast tego użyj 'identyczne' i trzymaj' == 'wokół wektoryzowanych porównań podczas podsekcji. – joran

+3

Jeśli zaczniesz przeciążać typowe operatory, Twój kod będzie poważnie nieprzenośny. O wiele lepiej jest dowiedzieć się, co robi każdy operator lub funkcja i użyć odpowiedniego narzędzia do właściwej pracy. –

Odpowiedz

7

W nawiązywaniu do @joran napotkasz problemy z liczbami zmiennoprzecinkowymi z == i != w prawie każdym innym języku. Jednym ważnym aspektem ich w R jest część wektoryzacji.

Znacznie lepiej zdefiniować nową funkcję almostEqual, fuzzyEqual lub podobną. Niefortunne jest, że nie ma takiej podstawowej funkcji. all.equal nie jest bardzo wydajny, ponieważ obsługuje wszystkie rodzaje obiektów i zwraca string opisujący różnicę, gdy w większości przypadków po prostu chcesz TRUE lub FALSE.

Oto przykład takiej funkcji. Jest wektoryzowany jak ==.

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 

... to jest około 2x szybciej niż all.equal dla wartości skalarnych, a znacznie szybciej wektorami.

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 - po kilku testach myślę, że jest błąd w tej funkcji. Rozważmy: matrixa = round (matrix (rnorm (9), nrow = 3, ncol = 3), 6) matrixb = matrixa - .001 almostEqual (matrixa, matrixb, tolerancja = .001) – SFun28

+0

Nawet w ten sposób powstaje FALSE czasami: almostEqual (matrixa, matrixb, tolerancja = .01) – SFun28

+0

@ SFun28 - Myślę, że kod jest poprawny. Zamiast tego wypróbuj 'all.equal', a otrzymasz również PRAWDA. To dlatego, że jest WSPÓŁCZESNA tolerancja.'rnorm' może dawać duże (3.5) lub małe (0.0003) liczby, ale twój błąd dodawany do matrixb jest zawsze' 0.001'. Zamiast tego wypróbuj 'matrixb <- matrixa * 1.001'. – Tommy

Powiązane problemy