生成间隔至少10的随机数

时间:2016-02-21 23:44:07

标签: r random numbers

我想生成100到1到100,000之间的数字,每个数字之间的空间至少为10。

一种方法是将100,000除以10,并做样本(1000,100)并得到答案,时间为10,但数字都以0结尾。

如何生成随机数,不仅以0结尾?

4 个答案:

答案 0 :(得分:2)

我无法想出一种非递归方式来做到这一点(首先想到的是为你的方法添加“摇摆”,但这几乎肯定会使一些观察结果彼此过于接近),但这将起作用:

set.seed(102438)
include <- 1:100000
smpl <- integer(100)

for (i in 1:length(smpl)){
  smpl[i] <- si <- sample(include, 1)
  #now remove anything within 10 of the current draw
  include <- setdiff(include, (si - 10L):(si + 10L))
}

min(abs(diff(smpl)))
# [1] 1105

答案 1 :(得分:2)

尝试拒绝抽样。不受限制地进行采样,如果任何两个小于10分钟,则将结果扔掉并再次进行直至成功:

repeat {
  s <- sample(100000, 100)
  mindiff <- min(diff(sort(s)))
  if (mindiff >= 10) break
}

从问题的措辞中不清楚,如果排序时连续数字的差异必须是10或更大,或者它们是否必须大于10.我假设前者但使用&gt;在if语句中,如果是后者。

示例从种子123开始,循环仅进行3次迭代(与其他答案的100次和100,000次迭代相比)。下面我们为可重现性添加了set.seed语句和print语句,以便我们可以看到使用了多少次迭代。

set.seed(123)
repeat {
  s <- sample(100000, 100)
  mindiff <- min(diff(sort(s)))
  print(mindiff)
  if (mindiff >= 10) break
}

,并提供:

[1] 8
[1] 1
[1] 17

答案 2 :(得分:0)

与@ G.Grothendieck类似,我想,重复抽样,但如果不符合您的标准则拒绝。

var getOrdinal = function(n) {
    var s = ["th", "st", "nd", "rd"],
    v = n % 100;
    return n + (s[(v - 20) % 10] || s[v] || s[0]);
};

var test = function(n) {
    v = n % 100;
    console.log(n, (v - 20) % 10, v, 0, getOrdinal(n))
};
for(i = 0; i < 130; i++) test(i);

答案 3 :(得分:0)

这是不依赖递归的东西:

mysample <- function(n, lower, upper, space) {
  b <- ceiling((upper - lower + 1) / (space - 1))
  bs <- sample(seq(2, b - 1, by = 2), n - 1)
  gr <- split(setdiff(1:b,bs), cumsum(c(0, diff(setdiff(1:b, bs))) != 1))
  out <- sapply(gr, function(x) (x[1] - 1) * (space - 1) + ceiling(runif(1) * length(x) * (space - 1)))
  out[n] <- min(out[n], upper)
  out
}

set.seed(123)
min(replicate(min(diff(mysample(100, 1, 100000, 10))), n = 1000))
# [1] 10

mysample会返回已排序的序列,但您当然可以使用sample(mysample(...))

该函数的思想是将区间[lower,upper]划分为长度space - 1的块和来自第2,第4,第6,...块的样本n-1块;这些将被禁止&#34;块,即我们将不会从这些块中获得任何数字。然后剩下的,&#34;允许&#34;块可以是例如第1,第2,第5;在这种情况下,我们有两组连续的块(第一和第二;第五),我们从对应于这两组块的间隔中采样两个数字。我还添加了一个小小的检查,以确定最大数字是否高于上限。

一些结果:

set.seed(123)
upper <- 100000
benchmark(
  mysample(100, 1, upper, 10), MichaelChirico(100, 1, upper, 10), 
  Grothendieck(100, 1, upper, 10), Jonathan(100, 1, upper, 10), 
  replications = 1, columns = c("test", "relative"))
#                                    test relative
# 3   Grothendieck(100, lower, upper, 10)        1
# 4       Jonathan(100, lower, upper, 10)      344
# 2 MichaelChirico(100, lower, upper, 10)     2133
# 1       mysample(100, lower, upper, 10)        4

upper <- 10000
benchmark(
  mysample(100, 1, upper, 10), MichaelChirico(100, 1, upper, 10), 
  Grothendieck(100, 1, upper, 10), Jonathan(100, 1, upper, 10), 
  replications = 1, columns = c("test", "relative"))
#                                    test relative
# 3   Grothendieck(100, lower, upper, 10)    132.5
# 4       Jonathan(100, lower, upper, 10)     56.0
# 2 MichaelChirico(100, lower, upper, 10)     27.5
# 1       mysample(100, lower, upper, 10)      1.0

,其中

MichaelChirico <- function(n, lower, upper, space) {
  include <- lower:upper
  smpl <- integer(n)
  for (i in 1:length(smpl)){
    smpl[i] <- si <- sample(include, 1)
    include <- setdiff(include, (si - space):(si + space))
  }
  smpl
}

Grothendieck <- function(n, lower, upper, space) {
  repeat {
    s <- sample(lower:upper, n)
    mindiff <- min(diff(sort(s)))
    if (mindiff >= space) break
  }
  s
}

Jonathan <- function(n, lower, upper, space) {
  min_gap <- space
  samp_vec <- sample(seq(lower,upper,1), 1)
  for (isamp in 1:n) {
    possible_new_value <- samp_vec[1]
    while(any(abs(samp_vec - possible_new_value) < min_gap)) {
      possible_new_value <- sample(seq(lower,upper,1), 1)
    }
    samp_vec <- c(samp_vec, possible_new_value)
  }
  samp_vec
}