1

I don't understand why this while loop is infinite:

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 for this:

    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;
        }
    });

Solution:

Sorry, the mistake was in another test, like describe by @Jon answer, when anyNumber equal a 1, infinite loop happens:

    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);
        }
    });
2
  • What's the value of limit? For example, if limit == 1 then it's an endless loop because of simple math. Commented Apr 21, 2012 at 19:16
  • Side note: You could make the code more DRY if you used a do...while loop. Commented Apr 21, 2012 at 19:22

1 Answer 1

7

Endless loop #1

The loop will be endless if limit == 1. Consider:

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

Math.random returns a number in the range [0, 1). Multiplying by limit does not change that, adding one brings it to [1, 2) so by definition Math.floor on that will return 1.

while (window.prevRandomNumber == actualRandomNumber) {
    actualRandomNumber = Math.floor((Math.random() * limit) + 1)
}

Here we have the same logic, so:

  • the first time the method is called it will return 1 (it will not go into a loop because prevRandomNumber is -1)
  • the second and subsequent times the method will never return because prevRandomNumber will be already 1

I can't see how the loop would be infinite if limit is a number greater than 1.

Endless loop #2

Consider what happens if limit is not a number.

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

Here, Math.random() * limit is going to be NaN, and so will the end result of the expression. So actualRandomNumber will always be equal to NaN. The method will return Nan the first time it's invoked and will not return the second time, for the same reason as above.

Solution

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

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

The first line fixes endless loop #2, and the second fixes loop #1 by adding 1 to limit before flooring the result. Therefore, if limit is 1 you will have

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

which is easy to see returns either 0 or 1 (and not always 1).

Sign up to request clarification or add additional context in comments.

5 Comments

Yeah, even if I call getRandomNumber(9) from test, the while loop still in infinite.
@AcazSouza: Works for me. Are you sure it's 9 and not "9"?
Wait... I got a strange behavior, my limit is not always 9... Why? If I call getRandomNumber(9); limit is not always 9...
Sorry, I'm sure limit is always 9, but still remains infinite.
@AcazSouza: I don't know what does to an infinite loop, but this code does not. See the link I gave above.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.