Ответ 1
Другой альтернативой является проверка дробной части:
x%%1==0
или, если вы хотите проверить в пределах определенного допуска:
min(abs(c(x%%1, x%%1-1))) < tol
Я с удивлением узнал, что у R нет удобной функции, чтобы проверить, является ли число целым.
is.integer(66) # FALSE
is.integer(x)
не проверяет, еслиx
содержит целые числа! Для этого, используйтеround
, как в функцииis.wholenumber(x)
в примерах.
В примере эта пользовательская функция используется как "обходной путь"
is.wholenumber <- function(x, tol = .Machine$double.eps^0.5) abs(x - round(x)) < tol
is.wholenumber(1) # is TRUE
Если бы мне пришлось написать функцию для проверки целых чисел, считая, что я не читал вышеприведенные комментарии, я бы написал функцию, которая будет идти что-то вдоль строк
check.integer <- function(x) {
x == round(x)
}
Где мой подход провалится? Какова была бы ваша работа, если бы вы были в моих гипотетических ботинках?
Другой альтернативой является проверка дробной части:
x%%1==0
или, если вы хотите проверить в пределах определенного допуска:
min(abs(c(x%%1, x%%1-1))) < tol
Здесь решение, использующее более простые функции и без хаков:
all.equal(a, as.integer(a))
Что еще, вы можете протестировать целый вектор сразу, если хотите. Здесь функция:
testInteger <- function(x){
test <- all.equal(x, as.integer(x), check.attributes = FALSE)
if(test == TRUE){ return(TRUE) }
else { return(FALSE) }
}
Вы можете изменить его, чтобы использовать *apply
в случае векторов, матриц и т.д.
Считывая документацию по языку R, as.integer
имеет больше общего с тем, как число хранится, чем если оно практически эквивалентно целому числу. is.integer
проверяет, объявлено ли число как целое число. Вы можете объявить целое число, поместив L
после него.
> is.integer(66L)
[1] TRUE
> is.integer(66)
[1] FALSE
Также функции, такие как round
, возвращают объявленное целое число, что вы делаете с x==round(x)
. Проблема с этим подходом заключается в том, что вы считаете практически целым числом. В примере используется меньшая точность для проверки эквивалентности.
> is.wholenumber(1+2^-50)
[1] TRUE
> check.integer(1+2^-50)
[1] FALSE
Таким образом, в зависимости от вашего приложения вы можете попасть в проблему таким образом.
Вот один, по-видимому, надежный способ:
check.integer <- function(N){
!grepl("[^[:digit:]]", format(N, digits = 20, scientific = FALSE))
}
check.integer(3243)
#TRUE
check.integer(3243.34)
#FALSE
check.integer("sdfds")
#FALSE
Это решение также допускает целые числа в научной нотации:
> check.integer(222e3)
[1] TRUE
Похоже, что вы не видите необходимости включать некоторую погрешность. Это не было бы необходимо, если бы все целые числа вводились как целые числа, однако иногда они возникают в результате арифметических операций, которые теряют определенную точность. Например:
> 2/49*49
[1] 2
> check.integer(2/49*49)
[1] FALSE
> is.wholenumber(2/49*49)
[1] TRUE
Обратите внимание, что это не слабость R, все компьютерное программное обеспечение имеет некоторые пределы точности.
От Hmisc::spss.get
:
all(floor(x) == x, na.rm = TRUE)
гораздо более безопасный вариант, IMHO, поскольку он "обходит" проблему точности машины. Если вы попробуете is.integer(floor(1))
, вы получите FALSE
. BTW, ваше целое не будет сохранено как целое, если оно больше, чем значение .Machine$integer.max
, которое по умолчанию равно 2147483647, поэтому либо измените значение integer.max
, либо выполните альтернативные проверки...
вы можете использовать простые условия if:
if(round(var) != var)
В R может быть определено числовое число или целое число с помощью функции класса. Обычно все числа хранятся как числовые и для явного определения числа как целого числа нам нужно указать "L" после номера.
Пример:
x < - 1
класс (х)
[1] "numeric"
x < - 1L
класс (х)
[1] "integer"
Надеюсь, это то, что нужно. Спасибо:)
Что может помочь это следующая строка:
x%%1==0
ИСТИНА: если x числовое без десятичных знаков
ЛОЖЬ: если x имеет десятичные дроби
Возвращает TRUE, если x числовое без десятичных знаков. Если x имеет десятичные дроби (например, x <- 3.5), возвращает FALSE.
Если вы предпочитаете не писать свою собственную функцию, попробуйте check.integer
из пакета installr.
В настоящее время используется ответ ВитошКа.
[ОБНОВЛЕНИЕ] ===================================================== ===============
Относительно ответа [СТАРЫЙ] здесь ниже, я обнаружил, что он работал, потому что я поместил все числа в один атомный вектор; один из них был персонажем, поэтому каждый стал персонажем.
Если мы используем список (следовательно, принуждение не происходит), все тесты проходят правильно, но один: 1/(1 - 0.98)
, который остается numeric
. Это связано с тем, что по умолчанию параметр tol
равен 100 *.Machine$double.eps
а это число намного меньше, чем в 50
. Так что, в основном, для такого рода чисел мы должны решить нашу терпимость!
Поэтому, если вы хотите, чтобы все тесты стали TRUE
, вы можете assertive::is_whole_number(x, tol = 200 *.Machine$double.eps)
В любом случае, я подтверждаю, что напористость IMO остается лучшим решением.
Здесь ниже представление для этого [ОБНОВЛЕНИЕ].
expect_trues_c <- c(
cl = sqrt(2)^2,
pp = 9.0,
t = 1 / (1 - 0.98),
ar0 = 66L,
ar1 = 66,
ar2 = 1 + 2^-50,
v = 222e3,
w1 = 1e4,
w2 = 1e5,
v2 = "1000000000000000000000000000000000001",
an = 2 / 49 * 49,
ju1 = 1e22,
ju2 = 1e24,
al = floor(1),
v5 = 1.0000000000000001 # this is under machine precision!
)
str(expect_trues_c)
#> Named chr [1:15] "2" "9" "50" "66" "66" "1" "222000" "10000" "1e+05" ...
#> - attr(*, "names")= chr [1:15] "cl" "pp" "t" "ar0" ...
assertive::is_whole_number(expect_trues_c)
#> Warning: Coercing expect_trues_c to class 'numeric'.
#> 2 9 50
#> TRUE TRUE TRUE
#> 66 66 1
#> TRUE TRUE TRUE
#> 222000 10000 100000
#> TRUE TRUE TRUE
#> 1e+36 2 1e+22
#> TRUE TRUE TRUE
#> 9.9999999999999998e+23 1 1
#> TRUE TRUE TRUE
expect_trues_l <- list(
cl = sqrt(2)^2,
pp = 9.0,
t = 1 / (1 - 0.98),
ar0 = 66L,
ar1 = 66,
ar2 = 1 + 2^-50,
v = 222e3,
w1 = 1e4,
w2 = 1e5,
v2 = "1000000000000000000000000000000000001",
an = 2 / 49 * 49,
ju1 = 1e22,
ju2 = 1e24,
al = floor(1),
v5 = 1.0000000000000001 # this is under machine precision!
)
str(expect_trues_l)
#> List of 15
#> $ cl : num 2
#> $ pp : num 9
#> $ t : num 50
#> $ ar0: int 66
#> $ ar1: num 66
#> $ ar2: num 1
#> $ v : num 222000
#> $ w1 : num 10000
#> $ w2 : num 1e+05
#> $ v2 : chr "1000000000000000000000000000000000001"
#> $ an : num 2
#> $ ju1: num 1e+22
#> $ ju2: num 1e+24
#> $ al : num 1
#> $ v5 : num 1
assertive::is_whole_number(expect_trues_l)
#> Warning: Coercing expect_trues_l to class 'numeric'.
#> There was 1 failure:
#> Position Value Cause
#> 1 3 49.999999999999957 fractional
assertive::is_whole_number(expect_trues_l, tol = 200 * .Machine$double.eps)
#> Warning: Coercing expect_trues_l to class 'numeric'.
#> 2.0000000000000004 9 49.999999999999957
#> TRUE TRUE TRUE
#> 66 66 1.0000000000000009
#> TRUE TRUE TRUE
#> 222000 10000 100000
#> TRUE TRUE TRUE
#> 1e+36 1.9999999999999998 1e+22
#> TRUE TRUE TRUE
#> 9.9999999999999998e+23 1 1
#> TRUE TRUE TRUE
expect_falses <- list(
bb = 5 - 1e-8,
pt1 = 1.0000001,
pt2 = 1.00000001,
v3 = 3243.34,
v4 = "sdfds"
)
str(expect_falses)
#> List of 5
#> $ bb : num 5
#> $ pt1: num 1
#> $ pt2: num 1
#> $ v3 : num 3243
#> $ v4 : chr "sdfds"
assertive::is_whole_number(expect_falses)
#> Warning: Coercing expect_falses to class 'numeric'.
#> Warning in as.this_class(x): NAs introduced by coercion
#> There were 5 failures:
#> Position Value Cause
#> 1 1 4.9999999900000001 fractional
#> 2 2 1.0000001000000001 fractional
#> 3 3 1.0000000099999999 fractional
#> 4 4 3243.3400000000001 fractional
#> 5 5 <NA> missing
assertive::is_whole_number(expect_falses, tol = 200 * .Machine$double.eps)
#> Warning: Coercing expect_falses to class 'numeric'.
#> Warning: NAs introduced by coercion
#> There were 5 failures:
#> Position Value Cause
#> 1 1 4.9999999900000001 fractional
#> 2 2 1.0000001000000001 fractional
#> 3 3 1.0000000099999999 fractional
#> 4 4 3243.3400000000001 fractional
#> 5 5 <NA> missing
Создано в 2019-07-23 пакетом представлением (v0.3.0)
[СТАРЫЙ] ===================================================== ==================
ИМО лучшее решение приходит от assertive
пакета (который, на данный момент, решает все положительные и отрицательные примеры в этой теме):
are_all_whole_numbers <- function(x) {
all(assertive::is_whole_number(x), na.rm = TRUE)
}
are_all_whole_numbers(c(
cl = sqrt(2)^2,
pp = 9.0,
t = 1 / (1 - 0.98),
ar0 = 66L,
ar1 = 66,
ar2 = 1 + 2^-50,
v = 222e3,
w1 = 1e4,
w2 = 1e5,
v2 = "1000000000000000000000000000000000001",
an = 2 / 49 * 49,
ju1 = 1e22,
ju2 = 1e24,
al = floor(1),
v5 = 1.0000000000000001 # difference is under machine precision!
))
#> Warning: Coercing x to class 'numeric'.
#> [1] TRUE
are_all_not_whole_numbers <- function(x) {
all(!assertive::is_whole_number(x), na.rm = TRUE)
}
are_all_not_whole_numbers(c(
bb = 5 - 1e-8,
pt1 = 1.0000001,
pt2 = 1.00000001,
v3 = 3243.34,
v4 = "sdfds"
))
#> Warning: Coercing x to class 'numeric'.
#> Warning in as.this_class(x): NAs introduced by coercion
#> [1] TRUE
Создано в 2019-07-23 пакетом представлением (v0.3.0)
Я не уверен, чего вы пытаетесь достичь. Но вот некоторые мысли:
1. Преобразовать в целое число:
num = as.integer(123.2342)
2. Проверьте, является ли переменная целой:
is.integer(num)
typeof(num)=="integer"