js 生成范围内不重复的随机数。

我的需求
在 0 - 3 之间(包含0与3)生成 2 个不重复的随机数。

我的方案
我没有使用do while的方案来做...

function randomNumbers($range){
    return $range[0] + Math.round(Math.random() * ($range[1] -  $range[0]));
}

// 生成随机数字
function generatedRandomNumbers($length,$range){
    var _randomNumber = randomNumbers($range),
        _array = [];
                    
    for(var i = 0;i < $length;i++){
        if(~_array.indexOf(_randomNumber)){
            _randomNumber = randomNumbers($range);
        }
        _array[i] = _randomNumber;
    }
    console.log(JSON.stringify(_array));
};

求助各位高手啦

阅读 20.1k
6 个回答

无重复的小范围随机和大范围随机是不一样的,小范围随机的思想基本上是随机排序再抽取其中一部分(通常就是前面几个)。大范围随机通常是直接在范围内产生随机数,再判断是否重复。

你这个是小范围的,所以很简单,一句话

[0,1,2,3].sort(() => Math.random() - 0.5).slice(0,2)

既然 [].sort(() => Math.random() - 0.5) 这种方法产生的随机数随机性不强,可以使用 Fisher–Yates shuffle 算法来做,说起来也不是多麻烦的事情,就是随机从剩余的数里抽取一个。

翻了一下我以前的某个回答,那是随机选一部分数据,应该还是切这个题的,那个回答里有个图可以帮助理解。那个如果选完就是洗牌了。

上代码(代码中生成了一个索引数组,目的是不改变原数组数据)

const data = [0, 1, 2, 3];

const r = Array.apply(null, { length: data.length })
    .map((n, i) => i)
    .map((n, i, all) => {
        const j = i + Math.floor(Math.random() * (all.length - i));
        const v = all[j];
        all[j] = n;
        return v;
    })
    .slice(0, 2)
    .map(i => {
        return data[i];
    });

console.log(r);

如果不要索引数组还简单些,但是会改变原数组顺序

const r = data
    .map((n, i, all) => {
        const j = i + Math.floor(Math.random() * (all.length - i));
        const v = all[j];
        all[j] = n;
        return v;
    })
    .slice(0, 2);

随手写了一个,但缺陷在于如果要显示1~100范围内随机且不同的100个数值,这种算法的效率很慢。所以最好是数池排除法+这种,通过计算max-min / num是否大于50%来切换两种算法,提高效率。

/*
 *    @param    number    最小值
 *    @param    number    最大值
 *    @param    number    个数
 *    @return    arr        输出随机值(会含最小、最大值)
 */
function randNum(min, max, num) {
    var arr = [],
        t;
    function fn(i) {
        for (i; i < num; i++) {
            t = parseInt(Math.random() * (max - min + 1) + min);
            for(var k in arr) {
                if (arr[k] == t) {
                    fn(i);
                    break;
                }
            }
            arr[i] = t;
        }
    }
    fn(0);
    return arr
}

console.log(randNum(0, 3, 2))
console.log(randNum(10, 20, 4))
console.log(randNum(1, 10, 5))
console.log(randNum(5, 8, 3))

昨天也看到了一个类似的问题,处理的不是很好,但是可以得到结果。


var x, y, arr=[];
for(x=0; x<4; x++) {
    for(y=0; y<4; y++) {
        if(x!=y) {
            
            var num = x == 0 ? ((x*10).toString() + y) : x*10 + y;
            arr.push(num);
        }
    }
}
console.log(arr.length, arr);

理解错误,忽略答案吧

[0,1,2,3].sort(function(){return Math.random() > 0.5}).slice(0,2)
function randomNum(min, max) {
  return min + Math.round(Math.random() * (max - min));
}

function random2() {
  var rdm1 = randomNum(0, 3);
  var rdm2 = randomNum(0, 3);

  if(rdm1 === rdm2) {
    return random2();
  }
  
  return [rdm1, rdm2];
}

随手

<HTML>
 <HEAD>
  <TITLE> New Document </TITLE>
  <SCRIPT LANGUAGE="JavaScript">

    function getNum(){
        var num = new Array();
        for(var i = 0; i < 10; i++){
            num[num.length] =  Math.ceil(Math.random() * 30);
        }
        console.log(num);
    }
 
    
 
  </SCRIPT>
 </HEAD>
 
 <BODY onload="getNum()">
   
 </BODY>
</HTML>
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏