0

専門家

  • (Web ページのテキスト ボックスから) 2 つの数値の間で一意の乱数を生成したいと考えています。
  • 配列を使用して数値を格納しています。ユーザーがボタンをクリックすると、最初の乱数が与えられ、配列に保存されます。ユーザーがもう一度ボタンをクリックすると、乱数が生成され、配列番号と比較され、異なる場合は保存されて表示されます。
  • 可能な最大数が表示される場合、配列をクリアしてユーザーに通知します。
  • コードを書きましたが、エラーが発生します: スタック オーバーフロー、または重複した結果が表示されることがあります。

誰でもコードに光を当てることができますか:

var allnums = new Array();
var num1= new Number;
var num2= new Number;

function funClick()
{
  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;
  }

  if (num1<num2) 
  {
    x = Math.floor(Math.random() * (num2 - num1 + 1)) + num1;
    funShow(x);
  }
  else
  {
    alert("You entered wrong number criteria!");  
  }
}

function funShow(x)
{
  var bolFound = false;
  for (var i=0;i<allnums.length;i++)
  {
    if((allnums[i])==x)
    {   
      funClick();
    }    
  }
  if (bolFound == false)
  {
    document.getElementById('rgen').innerText  = x;
    allnums.push(x);
  }
}
4

3 に答える 3

2

そのコードがどのようにスタック オーバーフローを生成しているのかわかりません ( へfunShowの呼び出しがありfunClick、への呼び出しがありますが、論理エラーのためにへの呼び出しが発生することはありません。エラーを修正すると、スタック オーバーフローが発生します)。 、ただし)、いくつかの問題があります。コメントを参照してください。funClickfunShowfunShowfunClick

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

これには 2 つの方法があります。これは基本的にあなたがやろうとしていたことですが、再帰はありません:

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(", ");
}

実例| ソース

問題は、ランダムにヒットする必要があるため、最後の数スロットを埋めるのに時間がかかることです。

もう 1 つの方法は、番号を順番に並べて配列を生成し、それを台無しにすることです。範囲が広い場合は、劇的に効率的になります。このようなもの:

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(", ");
}

実例| ソース

ただしnums.sort(...)ランダムに 1 回実行するだけでは、ランダムな結果が得られない可能性があります。詳細については、この記事を参照してください(そのリンクと以下の情報を提供してくれたeBusinessに感謝します。)

したがって、さらに進んで、さらにランダムな操作を投入したい場合があります。別の例を次に示します。

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(", ");
}

実例| ソース

これは、配列の並べ替えを開始点として行いますが、要素間のランダムなスワップも行います。それでも一定時間で実行されますが、配列の並べ替えを単独で使用するよりも良い結果が得られるはずです。当然、ディストリビューションをテストしたいと思うでしょう。

于 2013-01-12T08:19:08.873 に答える
0

Crowder の回答を編集できないため、配列をスクランブルする単純で偏りのない方法を次に示します。

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;
    }
}
于 2013-01-12T22:11:07.603 に答える