簡體   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