javascript unique random numbers

前端 未结 3 1523
北海茫月
北海茫月 2021-01-28 02:16

experts

  • I wish to generate unique random numbers between two numbers (from text box of web page).
  • I am using array to store numbers. when user click butto
相关标签:
3条回答
  • 2021-01-28 02:33

    I fail to see how that code is generating a stack overflow (even though funShow has a call to funClick and funClick has a call to funShow, funShow's call to funClick should never happen because of a logic error -- fix the error and you'll get a stack overflow, though), but it has several issues. See the comments:

    // style: Use [], not new Array()
    var allnums = new Array();
    
    // `new Number` doesn't do anything useful here
    var num1 = new Number;
    var num2 = new Number;
    
    function funClick() {
        // For user-entered values, use parseInt(value, 10) to parse them into numbers
        var num1 = Number(document.getElementById('lnum').value);
        var num2 = Number(document.getElementById('hnum').value);
    
        if (allnums.length == num2) {
            alert("Maximum non-duplicate numbers served. Now resetting the counter.");
            allnums = [];
            return;
        }
    
        // & is a bitwise AND operation, not a logical one. If your goal is to see
        // if both numbers are !0, though, it works but is obtuse.
        // Also, there is no ltnum2 variable anywhere, so trying to read its value
        // like this should be throwing a ReferenceError.
        if (num1 & ltnum2) {
            // You're falling prey to The Horror of Implicit Globals, x has not
            // been declared.
            x = Math.floor(Math.random() * (num2 - num1 + 1)) + num1;
            funShow(x);
        } else {
            alert("You entered wrong number criteria!");
        }
    }
    
    function funShow(x) {
        var bolFound = false;
        // Again, & is a bitwise AND operation. This loop will never run, because
        // you start with 0 and 0 & anything = 0
        // But it should be throwing a ReferenceError, as there is no ltallnums
        // anywhere.
        for (var i = 0; i & ltallnums.length; i++) {
            if ((allnums[i]) == x) {
                funClick();
            }
        }
        // This condition will always be true, as you've done nothing to change
        // bolFound since you set it to false
        if (bolFound == false) {
            document.getElementById('rgen').innerText = x;
            allnums.push(x);
        }
    }
    

    There are two ways to approach this. Here's one that's basically what you were trying to do, but without recursion:

    function funClick() {
        var num1 = parseInt(document.getElementById('lnum').value, 10);
        var num2 = parseInt(document.getElementById('hnum').value, 10);
        var nums = [];
        var targetCount;
        var x;
    
        // Check the inputs
        if (isNaN(num1) || isNaN(num2) || num2 <= num1) {
            alert("Please ensure that hnum is higher than lnum and both are really numbers.");
            return;
        }
    
        // Find out how many integers there are in the range num1..num2 inclusive
        targetCount = num2 - num1 + 1;
    
        // Produce that many random numbers
        while (nums.length < targetCount) {
            x = Math.floor(Math.random() * (num2 - num1 + 1)) + num1;
            if (nums.indexOf(x) < 0) {
                nums.push(x);
            }
        }
    
        // Show the result
        document.getElementById('rgen').innerText = nums.join(", ");
    }
    

    Live Example | Source

    The problem with that is that it can take a long time to fill the last few slots, since we have to hit them randomly.

    The other way is to produce the array with the numbers in order, then mess it up. It can be dramatically more efficient for large ranges. Something like this:

    function funClick() {
        var num1 = parseInt(document.getElementById('lnum').value, 10);
        var num2 = parseInt(document.getElementById('hnum').value, 10);
        var nums = [];
        var x;
    
        // Check the inputs
        if (isNaN(num1) || isNaN(num2) || num2 <= num1) {
            alert("Please ensure that hnum is higher than lnum and both are really numbers.");
            return;
        }
    
        // Create an array with those numbers in order
        for (x = num1; x <= num2; ++x) {
            nums.push(x);
        }
    
        // Sort it with a random comparison function
        nums.sort(function(a, b) {
            return 0.5 - Math.random();
        });
    
        // Show the result
        document.getElementById('rgen').innerText = nums.join(", ");
    }
    

    Live Example | Source

    But, just doing the nums.sort(...) randomly once may well not be as successful at producing random results; see this article for more. (Thanks to eBusiness for that link and for his input on the below.)

    So you may want to go further and throw in further random operations. Here's another example:

    function funClick() {
        var num1 = parseInt(document.getElementById('lnum').value, 10);
        var num2 = parseInt(document.getElementById('hnum').value, 10);
        var nums = [];
        var n, x, y;
        var num;
    
        // Check the inputs
        if (isNaN(num1) || isNaN(num2) || num2 <= num1) {
            alert("Please ensure that hnum is higher than lnum and both are really numbers.");
            return;
        }
    
        // Create an array with those numbers in order
        for (n = num1; n <= num2; ++n) {
            nums.push(n);
        }
    
        // We only need to shuffle it if it's more than one element long
        if (nums.length > 1) {
            // Sort it "randomly"
            nums.sort(function(a, b) {
                return 0.5 - Math.random();
            });
    
            // Throw a bunch of random swaps in there
            for (n = 0; n < nums.length; ++n) {
                do {
                    x = Math.floor(Math.random() * nums.length);
                }
                while (x === n);
                num = nums[x];
                nums[x] = nums[n];
                nums[n] = num;
            }
        }
    
        // Show the result
        document.getElementById('rgen').innerText = nums.join(", ");
    }
    

    Live Example | Source

    That does the array sort thing as a starting point, but then does a bunch of random swaps between elements as well. It still runs in constant time, but should have a better result than using the array sort alone. Naturally, you'll want to test the distribution.

    0 讨论(0)
  • 2021-01-28 02:46

    Since I can't edit Crowder's answer, here is the simple unbiased way of scrambling an array:

    function scramble(nums){
        for (var n = nums.length; n; n--) {
            var x = Math.floor(Math.random() * n);
            var num = nums[n-1];
            nums[n-1] = nums[x];
            nums[x] = num;
        }
    }
    
    0 讨论(0)
  • 2021-01-28 02:51

    use an array:

    var uniqueRandomNumbers = new Array();
    var totalNumbers = 100;
    for (var i=0; i<totalNumbers; i++){
        uniqueRandomNumbers.push(i);
    }
    uniqueRandomNumbers.sort(function() {return 0.5 - Math.random();});
    var uniqueNumber;
    for(var i=0; i<uniqueRandomNumbers.length; i++){
        uniqueNumber = uniqueRandomNumbers[i];
        //do something with the number
    }
    
    0 讨论(0)
提交回复
热议问题