javascript 如何生成两个不同的随机数?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25424602/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to generate two different random numbers?
提问by Francisco Costa
I need to generate two different random numbers, they can't be equal to each other or to a third number. I tried to use a lot of if's to cover every possibility but, it seems my algorithm skills are not that good.
我需要生成两个不同的随机数,它们不能彼此相等,也不能等于第三个数字。我尝试使用很多 if 来涵盖所有可能性,但是,似乎我的算法技能不是那么好。
Can anyone help me on this?
谁可以帮我这个事?
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;
}
}
This is what I have so far, the next step would be:
到目前为止,这是我所拥有的,下一步将是:
if (numberTwo == numberThree) {
(...)
}
Is my line of thought right? Note: Numbers generated need to be between 0 and 3. Thanks in advance.
我的思路对吗?注意:生成的数字需要在 0 到 3 之间。提前致谢。
采纳答案by Tasos K.
You can run a while
loop until all numbers are different.
您可以运行一个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);
Here is the jsfiddle with the above code based on @jfriend00's suggestion http://jsfiddle.net/x4g4kkwc/1.
这是基于@jfriend00 的建议http://jsfiddle.net/x4g4kkwc/1的上述代码的 jsfiddle 。
Here is the original working demo: http://jsfiddle.net/x4g4kkwc/
这是原始的工作演示:http: //jsfiddle.net/x4g4kkwc/
回答by jfriend00
You can create an array of random possibilities and then remove items from that array as they are used, selecting future random numbers from the remaining values in the array. This avoids looping trying to find a value that doesn't match previous items.
您可以创建一个随机可能性数组,然后在使用时从该数组中删除项目,从数组中剩余的值中选择未来的随机数。这避免了尝试查找与先前项目不匹配的值的循环。
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()};
}
Working demo: http://jsfiddle.net/jfriend00/vhy6jxja/
工作演示:http: //jsfiddle.net/jfriend00/vhy6jxja/
FYI, this technique is generally more efficient than looping until you get something new when you are asking to randomly select most of the numbers within a range because this just eliminates previously used numbers from the random set so it doesn't have to keep guessing over and over until it gets an unused value.
仅供参考,当您要求随机选择范围内的大多数数字时,这种技术通常比循环更有效,因为这只是从随机集中消除了以前使用过的数字,因此不必继续猜测直到它得到一个未使用的值。
回答by hugomg
This version minimizes the number of calls to random like you did, but is a bit simpler and not biased. In your version, there is a 2/4 chance that numberOne goes to 0, and a 1/4 chance if goes to 1 and 2. In my version there are equal odds of numberOne ending up as 0, 1 or 2).
此版本像您一样最大限度地减少了对 random 的调用次数,但更简单且没有偏见。在您的版本中,numberOne 变为 0 的几率为 2/4,变为 1 和 2 的几率为 1/4。在我的版本中,numberOne 变为 0、1 或 2 的几率相等)。
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);
Its a special case of the array-shuffling version deceze mentioned but for when you have only two numbers
它是提到的数组改组版本 deceze 的一个特例,但是当您只有两个数字时
回答by R2B2
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++;
}
You need to compare n2
with the minimum of n1
and n3
first to ensure you do not have an equality:
你需要比较n2
用最小的n1
和n3
首先要保证你没有一个平等的:
Suppose n1=1
and n3=2
. If you get n2=1
and compare it first with n3
, you won't increase n2
in the first step. In the second step, you would increase it since n2 >= n1
. In the end, n2 = 2 = n3
.
假设n1=1
和n3=2
。如果先获取n2=1
并与 比较n3
,则不会n2
在第一步中增加。在第二步中,您将增加它,因为n2 >= n1
。最后,n2 = 2 = n3
。
This algorithm guarantees to have a uniform distribution, and you only call twice Math.random()
.
这个算法保证有一个均匀的分布,你只调用两次Math.random()
。
回答by ChoiBedal
I'm not sure of what you're trying to do (or actually, why is your code so complicated for what I understood). It might not be the most optimized code ever, but here is my try :
我不确定您要做什么(或者实际上,为什么您的代码对于我的理解如此复杂)。它可能不是有史以来最优化的代码,但这是我的尝试:
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);
}
EDIT : Damn, too late ^^
编辑:该死的,太晚了^^
回答by Greck
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;
};
})();
回答by Ling Vu
ES 6 Version:
ES 6 版本:
This is basically a function like already mentioned above, but using the an Arrow function
and the Spread operator
这基本上是一个类似于上面已经提到的函数,但是使用 anArrow function
和Spread 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);
回答by jimm101
Be aware that back-to-back calls to Math.random()
triggers a bug in chromeas indicated here, so modify any of the other answers by calling safeRand()
below.:
要知道,背到后端呼叫Math.random()
触发一个在Chrome的错误指示在这里,通过调用所以修改任何其他的答案safeRand()
如下:
function safeRand() {
Math.random();
return Math.random();
}
This still isn't ideal, but reduces the correlations significantly, as every additional, discarded call to Math.random()
will.
这仍然不理想,但显着降低了相关性,因为每一个额外的、丢弃的Math.random()
意志调用。
回答by Adriweb
Generally, in pseudo-code, I do :
通常,在伪代码中,我这样做:
var nbr1 = random()
var nbr2 = random()
while (nbr1 == nbr2) {
nbr2 = random();
}
This way you'll get two different random numbers. With an additional condition you can make them different to another (3rd) number.
这样你会得到两个不同的随机数。通过附加条件,您可以使它们与另一个(第三个)数字不同。