Aca*_*uza 1 javascript qunit while-loop
我不明白为什么这个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;
}
Run Code Online (Sandbox Code Playgroud)
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;
}
});
Run Code Online (Sandbox Code Playgroud)
解:
对不起,错误是在另一个测试中,就像@Jon回答描述的那样,当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);
}
});
Run Code Online (Sandbox Code Playgroud)
如果,循环将是无止境的limit == 1.考虑:
var actualRandomNumber = Math.floor((Math.random() * limit) + 1);
Run Code Online (Sandbox Code Playgroud)
Math.random返回[0,1]范围内的数字.乘以limit不改变它,添加一个将它带到[1,2],因此根据定义Math.floor将返回1.
while (window.prevRandomNumber == actualRandomNumber) {
actualRandomNumber = Math.floor((Math.random() * limit) + 1)
}
Run Code Online (Sandbox Code Playgroud)
这里我们有相同的逻辑,所以:
1(它不会进入循环,因为它prevRandomNumber是-1)prevRandomNumber已经是1如果limit数字大于1,我无法看到循环是如何无限的.
考虑如果limit不是数字会发生什么.
var actualRandomNumber = Math.floor((Math.random() * limit) + 1);
Run Code Online (Sandbox Code Playgroud)
这Math.random() * limit将是NaN,表达式的最终结果也是如此.所以,actualRandomNumber将始终等于NaN.该方法将Nan在第一次调用时返回,并且不会返回第二次,原因与上述相同.
function getRandomNumber(limit) {
limit = Number(limit) || 9;
var actualRandomNumber = Math.floor(Math.random() * (limit + 1));
Run Code Online (Sandbox Code Playgroud)
第一行修复了无限循环#2,第二行修复了循环#1,在对结果进行平铺之前加1限制.因此,如果limit是1,你将拥有
Math.floor( /* something in [0, 1) */ * 2 )
Run Code Online (Sandbox Code Playgroud)
很容易看到返回0或1(并不总是 1).