随机数的组合问题(JavaScript描述)

随机数的组合问题在面试时是常常考的,好比以前我就被问到:“有一个能够生成1-5的随机数函数,怎样把它扩大到1-7?”面试

在解决这个问题以前,先来看看另一个比较简单的问题:“有一个能够生成1-7的函数,怎样把它缩小到1-5?”下面是一个生成1-7函数random7:dom

function random7() {
  return Math.floor(Math.random() * 7 + 1);
}

如何把它转成生成1-5的函数呢?这很简单:在一个循环里面调用random7,直到它的值小于等于5就结束循环并返回该随机数便可,以下:函数

function random5() {
  var r = random7();
  while(r > 5) {
    r = random7();
  }
  return r;
}

上面的思路就是:若是生成的随机数大于5,就继续调用random7,直到它小于等于5为止。好吧,回归正题,再来看一下1-5如何转成1-7吧。下面是一个随机生成1-5的函数:spa

function random5() {
  return Math.floor(Math.random() * 5 + 1);
}

 

咱们如今的目的是要把它扩大到1-7。有一种很天然的想法可能就是:一个random5()产生的随机数范围是1-5,那么两个random5()相加的范围就是2-10了,再减去1就是1-9了,因此,能够按照上面的思路,在random7里来个循环,若是小于等于7就结束循环而且返回。以下:code

function random7() {
  var r = random5() + random5() - 1;
  while(r > 7) {
    r = random5() + random5() - 1;
  }
  return r;
}

这样确实能够把1-5的范围扩大到1-7,可是问题来了:所谓随机函数,产生的每一个值的几率是相等的,可是上面的方法产生的值几率相等吗?咱们可使用几率论的组合知识算岀来:生成1有一种组合,就是random5() + random5() - 1;中的两个random5()均是1,生成2有两种组合,第一个random5()是1第二个是2,或者相反。显然,它们的几率是不等的。因此这种方法是不行的。blog

为了实现生成的每一个值的几率是相等的,就是使得每一个值的组合数相等。一种可行的方法是使得每一个值的组合只有一种,以下:it

function random7() {
  var r = (random5() - 1) * 5 + random5(); 
  while(r > 7) {
    r = (random5() - 1) * 5 + random5(); 
  }
  return r;
}

为何这样就会使得各个值的几率相等呢?首先来看一下(random5() - 1) * 5,容易算岀这个表达式生成的可选值是0,5,10,15,20,用它去跟random5()相加,由于random5()的可选值是1, 2,3,4,5,因此二者相加以后就会获得1-25之间的随机数,并且产生的每一个值的组合均只有一种,因此它们的几率也是相等的。io

也许有人会问,(random5() - 1) * 5,这里为何是乘以5而不是其余呢?这是由于乘以5以后和random5()相加,获得的数是连续的而且是等几率的。function

上面讨论的都是特殊情形1-5和1-7之间的转换,对于其余的通常情形,你们能够本身试试哈。class

相关文章
相关标签/搜索