检查数字是否为整数

时间:2010-08-13 12:30:39

标签: r integer rounding

我很惊讶地发现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)
}

我的方法会在哪里失败?如果你穿着我的假想鞋,那你的工作会是什么?

13 个答案:

答案 0 :(得分:100)

另一种选择是检查小数部分:

x%%1==0,

,或者

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

如果你想在一定的容忍范围内检查。

答案 1 :(得分:27)

这是一个使用更简单的功能而且没有黑客攻击的解决方案:

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

答案 2 :(得分:9)

阅读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

因此,根据您的应用程序,您可能会遇到麻烦。

答案 3 :(得分:9)

这是一种显然可靠的方式:

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

答案 4 :(得分:8)

您似乎没有看到需要包含一些容错。如果所有整数都以整数形式输入,则不需要它,但有时它们会因算术运算而失去一些精度。例如:

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

请注意,这不是R的弱点,所有计算机软件都有一定的精度限制。

答案 5 :(得分:6)

来自Hmisc::spss.get

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

更安全的选择,恕我直言,因为它“绕过”机器精度问题。如果您尝试is.integer(floor(1)),则会获得FALSE。顺便说一句,如果你的整数大于.Machine$integer.max值,那么你的整数将不会保存为整数,默认情况下为2147483647,所以要么改变integer.max值,要么做替代检查......

答案 6 :(得分:3)

你可以使用简单的if条件,如:

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

答案 7 :(得分:1)

在R中,数字是数字还是整数可以由类函数确定。通常所有数字都存储为数字,并明确定义一个数字作为整数,我们需要指定&#39; L&#39;在号码之后。

示例:

  

x < - 1

     

类(x)的

[1]&#34;数字&#34;

  

x < - 1L

     

类(x)的

[1]&#34;整数&#34;

我希望这是我们所需要的。谢谢:))

答案 8 :(得分:0)

如果您不想编写自己的函数,请尝试从软件包安装程序中使用check.integer

当前it uses VitoshKa的回答。

答案 9 :(得分:0)

[UPDATE] ============================================ ==================

在下面的[OLD]回答中,我发现它起作用是因为我将所有数字都放在一个原子向量中。其中一个是角色,所以每个人都成为角色。

如果我们使用列表(因此不会发生强制转换),则所有测试均正确通过,但只有一个:1/(1 - 0.98),仍然是numeric。这是因为tol参数在默认情况下为100 * .Machine$double.eps,并且该数字与50的距离远小于其两倍。因此,基本上,对于这种数字,我们必须来决定我们的容忍度!

因此,如果您希望所有测试都成为TRUE,则可以assertive::is_whole_number(x, tol = 200 * .Machine$double.eps)

无论如何,我确认IMO自信仍然是最佳解决方案。

下面是此[UPDATE]的代表。

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

reprex package(v0.3.0)于2019-07-23创建

[OLD] ============================================= =====================

IMO最好的解决方案来自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

reprex package(v0.3.0)于2019-07-23创建

答案 10 :(得分:0)

一次也可以使用dplyr::near

library(dplyr)

near(a, as.integer(a))

它适用于任何向量a,并且具有可选的公差参数。

答案 11 :(得分:0)

对于向量 mm[round(m) != m] 将返回向量中非整数值的索引。

答案 12 :(得分:-3)

我不确定你想要完成什么。但这里有一些想法:
1.转换为整数:
num = as.integer(123.2342)
2.检查变量是否为整数:
is.integer(num)
typeof(num)=="integer"