Проверьте, является ли число целым

Я с удивлением узнал, что у 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)
}

Где мой подход провалится? Какова была бы ваша работа, если бы вы были в моих гипотетических ботинках?

Ответ 1

Другой альтернативой является проверка дробной части:

x%%1==0

или, если вы хотите проверить в пределах определенного допуска:

min(abs(c(x%%1, x%%1-1))) < tol

Ответ 2

Здесь решение, использующее более простые функции и без хаков:

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 в случае векторов, матриц и т.д.

Ответ 3

Считывая документацию по языку 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

Таким образом, в зависимости от вашего приложения вы можете попасть в проблему таким образом.

Ответ 4

Вот один, по-видимому, надежный способ:

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

Ответ 5

Похоже, что вы не видите необходимости включать некоторую погрешность. Это не было бы необходимо, если бы все целые числа вводились как целые числа, однако иногда они возникают в результате арифметических операций, которые теряют определенную точность. Например:

> 2/49*49
[1] 2
> check.integer(2/49*49)
[1] FALSE 
> is.wholenumber(2/49*49)
[1] TRUE

Обратите внимание, что это не слабость R, все компьютерное программное обеспечение имеет некоторые пределы точности.

Ответ 6

От Hmisc::spss.get:

all(floor(x) == x, na.rm = TRUE)

гораздо более безопасный вариант, IMHO, поскольку он "обходит" проблему точности машины. Если вы попробуете is.integer(floor(1)), вы получите FALSE. BTW, ваше целое не будет сохранено как целое, если оно больше, чем значение .Machine$integer.max, которое по умолчанию равно 2147483647, поэтому либо измените значение integer.max, либо выполните альтернативные проверки...

Ответ 7

вы можете использовать простые условия if:

if(round(var) != var)­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­

Ответ 8

В R может быть определено числовое число или целое число с помощью функции класса. Обычно все числа хранятся как числовые и для явного определения числа как целого числа нам нужно указать "L" после номера.

Пример:

x < - 1

класс (х)

[1] "numeric"

x < - 1L

класс (х)

[1] "integer"

Надеюсь, это то, что нужно. Спасибо:)

Ответ 9

Что может помочь это следующая строка:

x%%1==0

ИСТИНА: если x числовое без десятичных знаков
ЛОЖЬ: если x имеет десятичные дроби

Возвращает TRUE, если x числовое без десятичных знаков. Если x имеет десятичные дроби (например, x <- 3.5), возвращает FALSE.

Ответ 10

Если вы предпочитаете не писать свою собственную функцию, попробуйте check.integer из пакета installr.

В настоящее время используется ответ ВитошКа.

Ответ 11

[ОБНОВЛЕНИЕ] ===================================================== ===============

Относительно ответа [СТАРЫЙ] здесь ниже, я обнаружил, что он работал, потому что я поместил все числа в один атомный вектор; один из них был персонажем, поэтому каждый стал персонажем.

Если мы используем список (следовательно, принуждение не происходит), все тесты проходят правильно, но один: 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)

Ответ 12

Я не уверен, чего вы пытаетесь достичь. Но вот некоторые мысли:
1. Преобразовать в целое число:
num = as.integer(123.2342)
2. Проверьте, является ли переменная целой:
is.integer(num)
typeof(num)=="integer"