javascript - 为什么这个 while Javascript 循环是无限的?

标签 javascript while-loop qunit

我不明白为什么这个 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/

相关文章:

java - while循环,似乎无法让它获得正确的数据

testing - 对象被销毁后,Ember 无法调用 writableChainWatchers

javascript - 在 webhook 嵌入中使用 base64 图像的discordjs

未定义错误命名空间的 Javascript 调用 WCF 服务

javascript - 所有按钮都具有相同的宽度 - jQuery

javascript - Mockjax 在同一个测试文件中两次?

javascript - 在 QUnit 测试中设置 $(this) 的范围

javascript - Jquery 删除 innertext 但保留 html

c++ - 可能有多个 while (cin>>input)

amazon-web-services - 亚马逊 Redshift 中的while循环