检查数字是否为正自然数的最快方法是什么? (在R中)

时间:2010-12-30 11:35:59

标签: performance r

我很感激如何做到这一点,所以我们可以相互比较。

这是一个开头的:

is.natural <- function(x)
{
     x>0 && identical(round(x), x)
}

5 个答案:

答案 0 :(得分:5)

docs提出了类似的方法,所以我怀疑你会变得更好。请记住包含epsilon以考虑精度问题!

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 ...

答案 1 :(得分:3)

请注意,identical()也会检查存储类型:is.natural(1L)返回FALSE,因为typeof(1L)integertypeof(round(1L))为{ {1}}。作为marcog的替代方案,我建议使用以下函数,使用double进行检查并处理复数:

all.equal()

答案 2 :(得分:2)

另一个解决方案是使用一些算术:

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

现在,当检查所有解决方案时,结果发现Tal和caracal之一没有给出正确的结果:

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
}

然后:

> 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

关于时间安排:

> 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 

这使得marcog成为赢家。

答案 3 :(得分:2)

您应该始终记住整数大小限制:.Machine$integer.max。即使您进行某种“检查”,如果给定的数值超出限制,R会将其视为double,并以不同的方式存储。

> (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"

答案 4 :(得分:1)

您需要两个测试:大于0并且足够接近整数。相同的()测试经常失败,因为它还会检查无关的属性和存储模式。 zapsmall提供将舍入限制为特定数量的数字的能力,并且以可以应用于候选值的向量的方式这样做。如果需要,您可以调整有效位数。

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

编辑:关于检查范围是一个很好的观点,因此添加了。