我不明白为什么这个 while
循环是无限的:
window.prevRandomNumber = -1;
function getRandomNumber(limit) {
if (!limit)
limit = 9;
var actualRandomNumber = Math.floor((Math.random() * limit) + 1);
while (window.prevRandomNumber == actualRandomNumber) {
actualRandomNumber = Math.floor((Math.random() * limit) + 1)
}
window.prevRandomNumber = actualRandomNumber;
return actualRandomNumber;
}
QUnit 测试:
test("getRandomNumber() should never return the same number once and again", function () {
//http://www.askageek.com/2006/01/31/javascript-random-function-that-does-not-return-two-consecutive-identical-results/
var prevNumber, actualNumber, assertResult;
for (var i = 0; i <= 200; i++) {
actualNumber = getRandomNumber();
assertResult = prevNumber != actualNumber;
equal(assertResult, true);
if (!assertResult)
break;
prevNumber = actualNumber;
}
});
解决方案:
抱歉,错误是在另一个测试中,如@Jon answer 所描述的,当 anyNumber 等于 1 时,发生无限循环:
test("getRandomNumber(anyNumber) should return a number between 1..anyNumber", function () {
var anyNumber, result;
for (var i = 0; i <= 100; i++) {
anyNumber = Math.floor((Math.random() * 9) + 1);
result = getRandomNumber(anyNumber);
equal((0 < result && result < (anyNumber + 1)), true);
}
});
最佳答案
无限循环#1
如果limit == 1
,循环将无限循环。考虑:
var actualRandomNumber = Math.floor((Math.random() * limit) + 1);
Math.random
返回 [0, 1) 范围内的数字。乘以 limit
不会改变它,加一会得到 [1, 2) 所以根据定义 Math.floor
将返回 1
.
while (window.prevRandomNumber == actualRandomNumber) {
actualRandomNumber = Math.floor((Math.random() * limit) + 1)
}
这里我们有相同的逻辑,所以:
- 第一次调用该方法时,它将返回
1
(不会进入循环,因为prevRandomNumber
为 -1) - 该方法将永远不会返回第二次和后续时间,因为
prevRandomNumber
已经是 1
如果 limit
是一个大于 1 的数字,我看不出循环怎么会是无限的。
无限循环#2
考虑如果 limit
不是数字会发生什么。
var actualRandomNumber = Math.floor((Math.random() * limit) + 1);
在这里,Math.random() * limit
将是 NaN
,表达式的最终结果也是如此。所以 actualRandomNumber
将总是等于NaN
。该方法将在第一次调用时返回 Nan
,并且不会在第二次调用时返回,原因与上述相同。
解决方案
function getRandomNumber(limit) {
limit = Number(limit) || 9;
var actualRandomNumber = Math.floor(Math.random() * (limit + 1));
第一行修复了无限循环 #2,第二行修复了循环 #1,方法是在对结果进行取整之前将 limit 加 1。因此,如果 limit
为 1,您将拥有
Math.floor( /* something in [0, 1) */ * 2 )
很容易看到返回 0 或 1(而不是总是 1)。
关于javascript - 为什么这个 while Javascript 循环是无限的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10262146/