views:

169

answers:

6

I was surprised to learn that R doesn't come with a handy function to check if the number is integer.

is.integer(66) # FALSE

The help files warns:

is.integer(x) does not test if x contains integer numbers! For that, use round, as in the function is.wholenumber(x) in the examples.

The example has this custom function as a "workaround"

is.wholenumber <- function(x, tol = .Machine$double.eps^0.5)  abs(x - round(x)) < tol
is.wholenumber(1) # is TRUE

If I would have to write a function to check for integers, assuming I hadn't read the above comments, I would write a function that would go something along the lines of

check.integer <- function(x) {
    x == round(x)
}

Where would my approach fail? What would be your work around if you were in my hypothetical shoes?

+2  A: 

reading the R language documentation. as.integer has more to do with how the number is stored than if it is practically equivalent to an integer. as.integer tests if the number is declared as an integer. You can declare an integer by putting a 'L' after it.

> is.integer(66L)
[1] TRUE

Also functions like round will return a declared integer, which is what you are doing with `x==round(x)'. The problem with this approach is what you consider to be practically an integer. The example uses less precision for testing equivalence.

> is.wholenumber(1+2^-50)
[1] TRUE
> check.integer(1+2^-50)
[1] FALSE

So depending on your application you could get into trouble that way.

Andrew Redd
A: 

I am not sure what you are trying to accomplish. But here are some thoughts:
1. Convert to integer:
num = as.integer(123.2342)
2. Check if a variable is an integer:
is.integer(num)
typeof(num)=="integer"

I'm just making sure the users enters an appropriate number - we're talking about the number of "subjects", which can be only an integer.
Roman Luštrik
A: 

Another alternative is to check the fractional part:

x%%1==0,

or,

x%%1<tol,

if you want to check within a certain tolerance.

James
+3  A: 

It appears that you do not see the need to incorporate some error tolerance. It would not be needed if all integers came entered as integers, however sometimes they come as a result of arithmetic operations that loose some precision. For example:

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

Note that this is not R's weakness, all computer software have some limits of precision.

Aniko
just in case some people don't quite get what happened here... if you enter as.integer(2/49*49) you get 1 !! [BTW, it is ever so frustrating that R doesn't present the result of the initial calculation as 2.0 to represent that the value has some decimal component) see... http://stackoverflow.com/questions/1535021/whats-the-biggest-r-gotcha-youve-run-across/3398868#3398868
John
+3  A: 

Here is one, apparently reliable way:

check.integer <- function(N){
    !length(grep("[^[:digit:]]", as.character(N)))
}


check.integer(3243)
#TRUE
check.integer(3243.34)
#FALSE
check.integer("sdfds")
#FALSE
VitoshKa
A: 

From Hmisc::spss.get:

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

much safer option, IMHO, since it "bypasses" the machine precision issue. If you try is.integer(floor(1)), you'll get FALSE. BTW, your integer will not be saved as integer if it's bigger than .Machine$integer.max value, which is, by default 2147483647, so either change the integer.max value, or do the alternative checks...

aL3xa