如何生成两个不同的随机数?

时间:2014-08-21 10:58:21

标签: javascript algorithm random

我需要生成两个不同的随机数,它们不能彼此相等或与第三个数相等。我尝试使用很多if来涵盖所有可能性,但似乎我的算法技能不是那么好。

有人可以帮我吗?

var numberOne = Math.floor(Math.random() * 4);
var numberTwo = Math.floor(Math.random() * 4);
var numberThree = 3; // This number will not always be 3

if((numberOne == numberThree) && (numberOne + 1 < 3)) {
    numberOne++;
} else if ((numberOne == numberThree) && (numberOne + 1 == 3)) {
    numberOne = 0;
}

if ((numberOne == numberTwo) && (numberOne+1 < 3)) {
    if (numberOne+1 < 3) {
        numberOne++;
    } else if(numberThree != 0) {
        numberOne = 0;
    }
}

这是我到目前为止所做的,下一步将是:

if (numberTwo == numberThree) {
    (...)
}

我的思路是否正确? 注意:生成的数字必须介于0和3之间。提前感谢。

9 个答案:

答案 0 :(得分:5)

您可以运行while循环,直到所有数字都不同。

// All numbers are equal
var numberOne = 3; 
var numberTwo = 3; 
var numberThree = 3; 

// run this loop until numberOne is different than numberThree
do {
    numberOne = Math.floor(Math.random() * 4);
} while(numberOne === numberThree);

// run this loop until numberTwo is different than numberThree and numberOne
do {
    numberTwo = Math.floor(Math.random() * 4);
} while(numberTwo === numberThree || numberTwo === numberOne);

以下是基于@jfriend00建议http://jsfiddle.net/x4g4kkwc/1的上述代码的jsfiddle。

以下是原始工作演示:http://jsfiddle.net/x4g4kkwc/

答案 1 :(得分:3)

您可以创建一个随机可能的数组,然后在使用它们时从该数组中删除项目,从数组中的其余值中选择未来的随机数。这样可以避免循环尝试查找与先前项不匹配的值。

function makeRandoms(notThis) {
    var randoms = [0,1,2,3];

    // faster way to remove an array item when you don't care about array order
    function removeArrayItem(i) {
        var val = randoms.pop();
        if (i < randoms.length) {
            randoms[i] = val;
        }
    }

    function makeRandom() {
        var rand = randoms[Math.floor(Math.random() * randoms.length)];
        removeArrayItem(rand);
        return rand;
    }

    // remove the notThis item from the array
    if (notThis < randoms.length) {
        removeArrayItem(notThis);
    }

    return {r1: makeRandom(), r2: makeRandom()};
}

工作演示:http://jsfiddle.net/jfriend00/vhy6jxja/

仅供参考,这种技术通常比循环更有效,直到你要求随机选择一个范围内的大多数数字时你会得到新的东西,因为这只是消除了随机集中以前使用过的数字所以它不需要不断猜测,直到它得到一个未使用的值。

答案 2 :(得分:3)

这个版本最大限度地减少了对你的随机调用次数,但是更简单,没有偏见。在你的版本中,有一个2/4的机会,numberOne变为0,如果变为1和2则有1/4的机会。在我的版本中,numberOne的相等几率最终为0,1或2)。 / p>

i0 = Math.floor(Math.random() * 4); //one of the 4 numbers in [0, 4), namely 3
i1 = Math.floor(Math.random() * 3); //only 3 possibilities left now
i2 = Math.floor(Math.random() * 2); //only two possibilities left now

x0 = i0;
x1 = i1 + (i1 >= i0 ? 1 : 0);
x2 = i2 + (i2 >= i0 ? 1 : 0) + (i2 >= i1 : 1 : 0);

它是一个特殊的数组洗牌版本deceze,但当你只有两个数字时

答案 3 :(得分:1)

我不确定你要做什么(或者实际上,为什么你的代码对我所理解的内容如此复杂)。它可能不是有史以来最优化的代码,但这是我的尝试:

var n3 = 3;
var n2 = Math.floor(Math.random() * 4);
var n1 = Math.floor(Math.random() * 4);

while(n1 == n3)
{
    n1 = Math.floor(Math.random() * 4);
}
while (n2 == n1 || n2 == n3)
{
    n2 = Math.floor(Math.random() * 4);
}
编辑:该死的,太晚了^^

答案 4 :(得分:1)

var rangeTo = 4;
var uniqueID = (function () {
    var id, cache = [];
    return function () {
        id = Math.floor((Math.random() * (new Date).getTime()) % rangeTo);
        var cacheLength = cache.length;
        if (cacheLength === rangeTo) {
            throw new Error("max random error");
        };
        var i = 0
        while (i < cacheLength) {
            if (cache[i] === id) {
                i = 0;
                id = Math.floor((Math.random() * (new Date).getTime()) % rangeTo);
            }
            else {
                i++;
            }
        }
        cache.push(id);
        return id;
    };
})();

答案 5 :(得分:0)

var n = 4; //to get two random numbers between 0 and 3
var n3 = 2; //for example
var n1 = Math.floor(Math.random(n-1));
var n2 = Math.floor(Math.random(n-2));
if(n1 >= n3) {
    n1++;
    if(n2 >= n3)
        n2++;
    if(n2 >= n1)
        n2++;
} else {
    if(n2 >= n1)
        n2++;
    if(n2 >= n3)
        n2++;
}

您需要首先将n2n1n3的最小值进行比较,以确保您没有平等:

假设n1=1n3=2。如果您获得n2=1并先将其与n3进行比较,则不会在第一步中增加n2。在第二步中,您将从n2 >= n1开始增加它。最后,n2 = 2 = n3

此算法保证统一分布,您只需调用两次Math.random()

答案 6 :(得分:0)

请注意,Math.random()的背对背电话会触发指示bug in chromehere,因此请通过调用以下safeRand()修改其他任何答案:

function safeRand() {
  Math.random();
  return Math.random();
}

这仍然不太理想,但会显着减少相关性,因为每次额外的,Math.random()被忽略的调用都会。

答案 7 :(得分:0)

ES 6版本:

这基本上是上面已经提到的功能,但是使用了Arrow functionSpread operator

const uniqueRandom = (...compareNumbers) => {
    let uniqueNumber;
    do {
        uniqueNumber = Math.floor(Math.random() * 4);
    } while(compareNumbers.includes(uniqueNumber));
    return uniqueNumber;
};

const numberOne = uniqueRandom();
const numberTwo = uniqueRandom(numberOne);
const numberThree = uniqueRandom(numberOne, numberTwo);

console.log(numberOne, numberTwo, numberThree);

答案 8 :(得分:-1)

通常,在伪代码中,我这样做:

var nbr1 = random()
var nbr2 = random()
while (nbr1 == nbr2) {
    nbr2 = random();
}

这样你就会得到两个不同的随机数。 在附加条件下,您可以使它们与另一个(第三)号码不同。