2010-08-13 4 views
72

Я был удивлен, узнав, что R не поставляется с удобной функцией для проверки того, является ли число целым.Проверьте, является ли число целым числом

is.integer(66) # FALSE 

help files warns:

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) 
} 

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

+0

Я хотел бы надеяться, что если «round (x)» будет реализовано правильно, результат применения его к целому будет всегда быть целым ... – Stephen

+0

Взгляните на FAQ по R http: // cran.r-project.org/doc/FAQ/R-FAQ.html#Why-doesn_0027t-R-think-these-numbers-are-equal_003f –

+4

> check.integer (9.0) [1] TRUE это не так. –

ответ

78

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

x%%1==0, 

или

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

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

+1

действительно ли предложение проверки толерантности действительно работает? 'x <- 5-1e-8; x %% 1' дает 0.9999999 (что подразумевает, если 'tol == 1e-5' например), что' x' ** не ** целое. –

+0

@BenBolker Хороший улов, он работает на позитивные возмущения, я думаю. Я изменил его на альтернативное решение, которое должно работать. – James

+2

@James, я думаю, что это должно быть 'min (abs (c (x %% 1, x %% 1-1))) Cath

6

Чтение документации на языке 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 

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

+0

Во второй строке говорится: «as.integer проверяет, объявлено ли число как целое число». но я уверен, что вы имели в виду «is.integer». Это редактирование только одного персонажа, поэтому я не мог легко его изменить. – PeterVermont

-3

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

+0

Я просто убедился, что пользователи входят в соответствующее число - мы говорим о количестве «предметов», которые могут быть только целыми числами. –

7

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

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

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

+3

на всякий случай некоторые люди не совсем понимают, что здесь произошло ... если вы входите в as.integer (2/49 * 49), вы получаете 1 !! [BTW, это так расстраивает, что R не представляет результат начального вычисления как 2.0, чтобы представить, что значение имеет некоторый десятичный компонент) см. ... http://stackoverflow.com/questions/1535021/ Whats-the-most-r-gotcha-youve-run-through/3398868 # 3398868 – John

8

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

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 
+1

Это не выглядит очень надежным для меня: 'check.integer (1e4)' is TRUE, а 'check.integer (1e5)' ЛОЖЬ. – wch

+0

@wch ОК адаптированы. вы можете теперь указать точку :) – VitoshKa

+4

-1 Это хуже, чем 'is.wholenumber' или любое другое решение, предоставленное в других ответах. Они не должны отличаться: 'check.integer (1e22); check.integer (1e23) '. Очевидно, вы можете изменить регулярное выражение, чтобы исправить это, но этот подход ужасен. (Комментарий приходит из атрибуции в пакете installr.) –

3

От Hmisc::spss.get:

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

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

27

Вот решение, использующее более простые функции и no hacks:

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

+7

Последний 'if'' else' может быть выполнен просто с помощью 'isTRUE (test)'. В самом деле, это все, что вам нужно, чтобы заменить предложения 'if'' else' и 'return', поскольку R автоматически возвращает результат последней оценки. –

+4

'' testInteger (1,0000001) '' [1] FALSE '' testInteger (1,00000001) '' [1] ИСТИНА – PatrickT

+1

'все (а == as.integer (а))' решает эту проблему! – Alex

1

вы можете использовать простой, если условие, как:

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

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

Пример:

х < - 1

класс (х)

[1] "цифровая"

х < - 1L

класс (х)

[1] "целое"

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

Смежные вопросы