Byłem zaskoczony, gdy dowiedziałem się, że R nie ma przydatnej funkcji do sprawdzenia, czy liczba jest liczbą całkowitą.
is.integer(66) # FALSE
is.integer(x)
nie sprawdza, czyx
zawiera liczby całkowite! W tym celu użyjround
, jak w funkcjiis.wholenumber(x)
w przykładach.
W przykładzie zastosowano tę funkcję niestandardową jako „obejście”
is.wholenumber <- function(x, tol = .Machine$double.eps^0.5) abs(x - round(x)) < tol
is.wholenumber(1) # is TRUE
Gdybym musiał napisać funkcję do sprawdzania liczb całkowitych, zakładając, że nie przeczytałem powyższych komentarzy, napisałbym funkcję, która poszłaby podobnie
check.integer <- function(x) {
x == round(x)
}
Gdzie moje podejście zawiodłoby? Co byś obejrzał, gdybyś był w moich hipotetycznych butach?
round(x)
zostanie poprawnie zaimplementowany, wynikiem zastosowania go do liczby całkowitej będzie zawsze ta liczba całkowita ...is.integer
sprawdza koncepcję obliczeniową,check.integer
funkcja użytkownika sprawdza matematyczny punkt widzenia.Odpowiedzi:
Inną alternatywą jest sprawdzenie części ułamkowej:
lub, jeśli chcesz sprawdzić w ramach określonej tolerancji:
źródło
x <- 5-1e-8; x%%1
Daje 0.9999999 (co oznacza, jeślitol==1e-5
, na przykład), którex
jest nie liczbą całkowitą.min(abs(c(x%%1, x%%1-1))) < tol
zamiast tegoabs(min(x%%1, x%%1-1)) < tol
, otrzymaszFALSE
za dowolną liczbę całkowitą ...as.integer(x) == x
? Nie odrzuci 3 lub 3.0 tak jakis.integer(x)
chciałbym i złapie 3.1.Oto rozwiązanie wykorzystujące prostsze funkcje i bez hacków:
Co więcej, jeśli chcesz, możesz przetestować cały wektor naraz. Oto funkcja:
Możesz go zmienić tak, aby był używany
*apply
w przypadku wektorów, macierzy itp.źródło
if
else
można zrobić po prostuisTRUE(test)
. Rzeczywiście, to wszystko, czego potrzebujesz, aby zamienićif
else
klauzulę ireturn
instrukcje, ponieważ R automatycznie zwraca wynik ostatniej oceny.testInteger(1.0000001)
[1] FALSEtestInteger(1.00000001)
[1] TRUEall(a == as.integer(a))
omija ten problem!Czytanie dokumentacji języka R
as.integer
ma więcej wspólnego z tym, jak liczba jest przechowywana, niż jeśli jest praktycznie równoważna liczbie całkowitej.is.integer
sprawdza, czy liczba jest zadeklarowana jako liczba całkowita. Możesz zadeklarować liczbę całkowitą, umieszczającL
po niej.Również funkcje takie jak
round
zwrócą zadeklarowaną liczbę całkowitą, czyli właśnie z nią korzystaszx==round(x)
. Problem z tym podejściem polega na tym, co uważamy za praktycznie liczbę całkowitą. Przykład używa mniejszej precyzji do testowania równoważności.W zależności od aplikacji możesz w ten sposób wpaść w kłopoty.
źródło
Oto jeden, pozornie niezawodny sposób:
To rozwiązanie dopuszcza również liczby całkowite w notacji naukowej:
źródło
check.integer(1e4)
jest PRAWDA, podczas gdycheck.integer(1e5)
jest FAŁSZ.is.wholenumber
jakiekolwiek inne rozwiązanie podane w innych odpowiedziach. To nie powinno być inaczej:check.integer(1e22); check.integer(1e23)
. Oczywiście możesz zmienić wyrażenie regularne, aby to naprawić, ale takie podejście jest okropne. (Komentarz pochodzi z przypisania w pakiecie instalacyjnym.)format(40, scientific = FALSE, digits = 20)
zamiast tego. Zaktualizowałem odpowiedź. Dzięki, że to zauważyłeś.1.0000000000000001 == 1L [1] TRUE
. Ale moje rozwiązanie jest lepsze, jeśli masz już liczbę w postaci ciągucheck.integer("1000000000000000000000000000000000001") [1] TRUE
Wydaje się, że nie widzisz potrzeby uwzględnienia pewnej tolerancji na błędy. Nie byłoby konieczne, gdyby wszystkie liczby całkowite były wprowadzane jako liczby całkowite, jednak czasami pojawiają się one w wyniku operacji arytmetycznych, które tracą pewną precyzję. Na przykład:
Zauważ, że to nie jest słabość R, każde oprogramowanie komputerowe ma pewne ograniczenia dokładności.
źródło
Z
Hmisc::spss.get
:znacznie bezpieczniejsza opcja, IMHO, ponieważ „omija” problem precyzji maszyny. Jeśli spróbujesz
is.integer(floor(1))
, dostanieszFALSE
. BTW, twoja liczba całkowita nie zostanie zapisana jako liczba całkowita, jeśli jest większa niż.Machine$integer.max
wartość, czyli domyślnie 2147483647, więc albo zmieńinteger.max
wartość, albo wykonaj alternatywne sprawdzenia ...źródło
x <- sqrt(2)^2
, toall(floor(x) == x, na.rm = TRUE)
wróćFALSE
możesz użyć prostego warunku if, takiego jak:
źródło
W R to, czy liczba jest liczbą, czy liczbą całkowitą, można określić za pomocą funkcji klasy. Ogólnie wszystkie liczby są przechowywane jako liczby i aby jawnie zdefiniować liczbę jako liczbę całkowitą, musimy określić „L” po liczbie.
Przykład:
[1] „numeryczny”
[1] „liczba całkowita”
Mam nadzieję, że to było potrzebne. Dzięki :)
źródło
[AKTUALIZACJA] =============================================== ===============
Szanując [STARY] odpowiedź poniżej, odkryłem, że zadziałała, ponieważ umieściłem wszystkie liczby w jednym wektorze atomowym; jeden z nich był postacią, więc każdy stał się postacią.
Jeśli użyjemy listy (stąd przymus nie zachodzi), wszystkie testy przebiegną poprawnie, z wyjątkiem jednego
1/(1 - 0.98)
:, który pozostajenumeric
. Dzieje się tak, ponieważtol
parametr jest domyślny,100 * .Machine$double.eps
a liczba ta jest daleka od50
podwojenia tej liczby. Tak więc, w zasadzie, do tego rodzaju liczb, możemy mieć do decydowania naszą tolerancję!Więc jeśli chcesz, aby wszystkie testy stały się możliwe
TRUE
, możeszassertive::is_whole_number(x, tol = 200 * .Machine$double.eps)
W każdym razie potwierdzam, że asertywność IMO pozostaje najlepszym rozwiązaniem.
Poniżej reprex dla tej [UPDATE].
Utworzony 2019-07-23 przez pakiet reprex (v0.3.0)
[STARY] =============================================== ==================
IMO najlepsze rozwiązanie pochodzi z
assertive
pakietu (który na razie rozwiązuje wszystkie pozytywne i negatywne przykłady w tym wątku):Utworzony 2019-07-23 przez pakiet reprex (v0.3.0)
źródło
Jeśli wolisz nie pisać własnej funkcji, spróbuj
check.integer
z instalatora pakietu . Obecnie używa odpowiedzi VitoshKa.Spróbuj również
check.numeric(v, only.integer=TRUE)
z pakietu varhandle , który ma tę zaletę, że jest wektoryzowany.źródło
Raz można też użyć
dplyr::near
:Ma zastosowanie do dowolnego wektora
a
i ma opcjonalny parametr tolerancji.źródło
Nie jestem pewien, co próbujesz osiągnąć. Ale oto kilka myśli:
1. Zamień na liczbę całkowitą:
num = as.integer(123.2342)
2. Sprawdź, czy zmienna jest liczbą całkowitą:
is.integer(num)
typeof(num)=="integer"
źródło