繁体   English   中英

为什么在Javascript循环无限的情况下执行此操作?

[英]Why this while Javascript loop is infinite?

我不明白为什么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答案所描述的,当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 ,表达式的最终结果也将是NaN 因此, actualRandomNumber始终等于NaN 出于与上述相同的原因,该方法将在第一次被调用时返回Nan ,而第二次将不会返回。

function getRandomNumber(limit) {
    limit = Number(limit) || 9;

    var actualRandomNumber = Math.floor(Math.random() * (limit + 1));

第一行修复了无限循环#2,第二行修复了循环#1,在下限结果之前,将1加到极限。 因此,如果limit为1,您将拥有

Math.floor( /* something in [0, 1) */ * 2 )

很容易看到它返回0或1(并不总是 1)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM