What is the fastest way to check if a number is a positive integer? (in R)

I would appreciate any idea on how to do this, so we can compare them with each other.

Here's how to get started:

is.natural <- function(x) { x>0 && identical(round(x), x) } 
+4
source share
5 answers

docs offer a similar method, so I doubt you will get better. Remember to enable epsilon to take into account accuracy issues!

 is.naturalnumber <- function(x, tol = .Machine$double.eps^0.5) x > tol & abs(x - round(x)) < tol is.naturalnumber(1) # is TRUE (x <- seq(1,5, by=0.5) ) is.naturalnumber( x ) #--> TRUE FALSE TRUE ... 
+5
source

Remember that identical() also checks the type of storage: your is.natural(1L) returns FALSE , because typeof(1L) is integer , but typeof(round(1L)) is double . As an alternative to marcog, I suggest the following function that uses all.equal() to check and process complex numbers:

 is.natural <- function(x, tol = .Machine$double.eps^0.5) { (abs(Im(x)) < tol) && (abs(Re(x)) > tol) && isTRUE(all.equal(x, round(x), tolerance=tol, check.attributes=FALSE, check.names=FALSE)) } 
+3
source

Another solution is to use a bit of arithmetic:

 is.natural2 <- function(x,tol=.Machine$double.eps^0.5){ sign(x) - abs(x-round(x)) >= 1-tol } 

Now, checking all the solutions, it turned out that one of Tal and one of the caracal did not give the correct result:

 is.natural <- function(x) { x>0 & identical(round(x), x) } is.natural2 <- function(x,tol=.Machine$double.eps^0.5){ sign(x) - abs(x-round(x)) >= 1-tol } is.natural3 <- function(x, dig=15){ x > 0 & zapsmall(x, dig) == round(x) } is.natural4 <- function(x,tol=.Machine$double.eps^0.5){ x > 0 & isTRUE(all.equal(x,round(x), tolerance=tol, check.attributes=FALSE, check.names=FALSE)) } is.naturalnumber <- function(x, tol = .Machine$double.eps^0.5){ x > 0 & abs(x - round(x)) < tol } 

Then:

 > X <- (seq(0,3,by=0.5)^0.5)^2 > is.natural(X) [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE # wrong > is.natural2(X) [1] FALSE FALSE TRUE FALSE TRUE FALSE TRUE > is.natural3(X) [1] FALSE FALSE TRUE FALSE TRUE FALSE TRUE > is.natural4(X) [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE # wrong > is.naturalnumber(X) [1] FALSE FALSE TRUE FALSE TRUE FALSE TRUE 

Regarding time:

 > X <- (seq(0,1000000,by=0.5)^0.5)^2 > system.time(is.natural2(X)) user system elapsed 0.24 0.03 0.26 > system.time(is.natural3(X)) user system elapsed 0.67 0.00 0.67 > system.time(is.naturalnumber(X)) user system elapsed 0.22 0.01 0.23 

what makes marcogue a winner.

+2
source

You should always have a limit on the size of an integer: .Machine$integer.max . Even if you perform some kind of β€œcheck”, if the given numerical value exceeds the limit, R will see it as a double , and it will be stored differently.

 > (x <- as.integer(.Machine$integer.max + 1)) [1] NA Warning message: NAs introduced by coercion > (x <- as.double(.Machine$integer.max + 1)) [1] 2147483648 > typeof(x) [1] "double" > x <- 2147483647L > typeof(x) [1] "integer" > x <- 2147483648L Warning message: non-integer value 2147483648 qualified with L; using numeric value > typeof(x) [1] "double" 
+2
source

You need two tests: greater than 0 and close enough to an integer. Testing identical () too often happens because it also checks for external attributes and storage mode. Zapsmall provides the ability to limit rounding to a certain number of digits and does so in a way that can be applied to candidate value vectors. You can change the number of significant digits if necessary.

 is.natural <- function(x, dig=15){ x > 0 & zapsmall(x, dig) == round(x) & x < .Machine$integer.max } x <- (2^0.5)^2 x ==2 # [1] FALSE (machine mathematics) is.natural(x) # [1] TRUE 

Edit: A good point was made to check the range, so it was added.

+1
source

Source: https://habr.com/ru/post/1333782/


All Articles