检查数字是否为整数。

144

我很惊讶地发现R没有一个方便的函数来检查数字是否为整数。

is.integer(66) # FALSE

帮助文件警告

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

我的方法在哪些情况下会失败?如果你处于我假设的境地中,你会采用什么样的方法绕过这些问题?


我希望如果 round(x) 被正确实现,将其应用于整数的结果始终是该整数... - Stephen
1
请查看关于R的常见问题解答:http://cran.r-project.org/doc/FAQ/R-FAQ.html#Why-doesn_0027t-R-think-these-numbers-are-equal_003f - Richie Cotton
5
检查整数(9.0) [1] TRUE 不是。 - Peng Peng
@PengPeng,VitoshKa在被接受的答案中修复了这个问题。 - Roman Luštrik
4
我认为关于整数的数学和计算概念存在混淆。函数 is.integer 检查计算概念,而 check.integer 用户函数则检查数学角度。 - João Daniel
14个回答

1
这是我使用Rcpp尝试解决的方案,用于检查所有数字是否为整数的情况。
我编写了一个函数,基本上通过循环遍历x,并使用条件abs(round(x) - x) < tol来判断是否存在非整数数字,如果有则返回FALSE。所以如果你的向量开头可能有小数,这个函数非常有用。

Rcpp函数

library(Rcpp)

Rcpp::cppFunction(
'bool is_whole_num(NumericVector x) {
  double tol = sqrt(std::numeric_limits<double>::epsilon());
  bool has_decimal;
  double diff;
  bool out = true;
  for (int i = 0; i < x.length(); ++i) {
    diff = abs(round(x[i]) - x[i]);
    has_decimal = !(diff < tol);
    if (has_decimal && !NumericVector::is_na(x[i])){
      out = false;
      break;
    }
  }
  return out;
}'
)

基准

x1 <- c(1:10^7, 0.01)
x2 <- c(0.01, 1:10^7)

bench::mark(james = all(x1%%1==0),
            iterator = isTRUE(all.equal(x1, as.integer(x1))),
            me = is_whole_num(x1))
# A tibble: 3 x 13
  expression      min   median `itr/sec` mem_alloc `gc/sec` n_itr  n_gc total_time result    memory    
  <bch:expr> <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl> <int> <dbl>   <bch:tm> <list>    <list>    
1 james       236.5ms  239.1ms      4.18  114.44MB     2.09     2     1      478ms <lgl [1]> <Rprofmem>
2 iterator    226.2ms    234ms      4.27  305.18MB     0        3     0      702ms <lgl [1]> <Rprofmem>
3 me           53.2ms   55.8ms     17.7     2.49KB     0        9     0      507ms <lgl [1]> <Rprofmem>
# i 2 more variables: time <list>, gc <list>
bench::mark(james = all(x2%%1==0),
            iterator = isTRUE(all.equal(x2, as.integer(x2))),
            me = is_whole_num(x2))
# A tibble: 3 x 13
  expression      min   median `itr/sec` mem_alloc `gc/sec` n_itr  n_gc total_time result    memory    
  <bch:expr> <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl> <int> <dbl>   <bch:tm> <list>    <list>    
1 james       227.1ms  236.8ms      4.24  114.44MB     0        3     0    707.2ms <lgl [1]> <Rprofmem>
2 iterator    203.4ms  203.4ms      4.92  305.18MB     4.92     1     1    203.4ms <lgl [1]> <Rprofmem>
3 me            1.4us    1.8us 510441.      2.49KB     0    10000     0     19.6ms <lgl [1]> <Rprofmem>
# i 2 more variables: time <list>, gc <list>

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

0

也可以使用 dplyr::near

library(dplyr)

near(a, as.integer(a))

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


-5

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


我只是确保用户输入一个适当的数字 - 我们说的是“主题”的数量,这只能是整数。 - Roman Luštrik

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接