简体   繁体   English

简单的 for 循环似乎无法正常工作

[英]Simple for loop does not seem work properly

I'm having a trouble to get an array with numbers from 1 to 16 randomly without repetition.我在不重复的情况下随机获取一个包含 1 到 16 数字的数组时遇到了麻烦。 I made num array to put numbers from createNum function.我制作了num数组来放置来自createNum函数的数字。

The createNum function has a for loop which gets numbers from 1 to 16 until if statement push 16 numbers into num array. createNum函数有一个 for 循环,它获取从 1 到 16 的数字,直到 if 语句将 16 个数字推入num数组。

At the end, I run createNum() and display numbers on the web.最后,我运行 createNum() 并在网络上显示数字。 While I'm making this code it sometimes worked but now it's not working.当我制作这段代码时,它有时会起作用,但现在不起作用。

can somebody point out where I made mistakes?有人能指出我哪里出错了吗?

let num = [];

function createNum () {
    for (i = 0; i <= 15;) {
        let numGen = Math.floor(Math.random() * 15) + 1;
        if (!num.includes(numGen)) {
            num.push(numGen);
            i++;
        };
    };
}
console.log(createNum());
document.getElementById("selectedNumbersShownHere").innerHTML = num;
console.log(num);

Your loop seems never finish because the probability to get the last value is very low, and never can happen in a short time.您的循环似乎永远不会完成,因为获得最后一个值的概率非常低,而且永远不会在短时间内发生。

Plus :加:
your formula is wrong : let numGen = Math.floor(Math.random() * 15) + 1;你的公式是错误的let numGen = Math.floor(Math.random() * 15) + 1;
and should be................: let numGen = Math.floor(Math.random() * 16) + 1;并且应该是……: let numGen = Math.floor(Math.random() * 16) + 1; value 16值 16

see => Generating random whole numbers in JavaScript in a specific range?请参阅 => 在 JavaScript 中生成特定范围内的随机整数?

do this:做这个:

 function createNum() { let num =[], lastOne =136; // 136 = 1 +2 +3 + ... +16 for (;;) { let numGen = Math.floor(Math.random() *16) +1; if (!num.includes(numGen)) { lastOne -= numGen; if (num.push(numGen)>14) break; } } num.push(lastOne); // add the missing one (optimizing) return num; } let unOrdered_16_vals = createNum(); /* document.getElementById("selectedNumbersShownHere").textContent = unOrdered_16_vals.join(''); */ console.log( JSON.stringify( unOrdered_16_vals ), 'length=', unOrdered_16_vals.length ); console.log( 'in order = ', JSON.stringify( unOrdered_16_vals.sort((a,b)=>ab) ) );

remark : The push() method adds one or more elements to the end of an array and returns the new length of the array.备注: push()方法将一个或多个元素添加到数组的末尾并返回数组的新长度

This is because Math.random() never returns 1, so at the end Math.floor(Math.random() * 15) will returns maximum 14 and adding it to 1 will get you maximum 15. Use Math.ceil instead of Math.floor ie这是因为Math.random()永远不会返回 1,所以最后Math.floor(Math.random() * 15)将返回最大值 14,并将其添加到 1 将得到最大值 15。使用Math.ceil而不是Math.floor

let num = [];

function createNum () {
    for (i = 0; i <=15;) {
        let numGen = Math.ceil(Math.random() * 16);
        console.log(numGen)
        if (!num.includes(numGen)) {
            num.push(numGen);
             i++;
        };
    };
}
console.log(createNum());
document.getElementById("selectedNumbersShownHere").innerHTML = num;
console.log(num);

Hope it helps!希望能帮助到你!

for (i = 0; i <= 15;) generates 16 numbers, but Math.floor(Math.random() * 15) + 1 only have 15 possible values (1~15). for (i = 0; i <= 15;)生成 16 个数字,但Math.floor(Math.random() * 15) + 1只有 15 个可能的值(1~15)。

A shuffle function is recommended.推荐使用shuffle功能。 Your function would be slow if you generate a large size shuffled array.如果你生成一个大尺寸的混洗数组,你的函数会很慢。

How can I shuffle an array? 我怎样才能洗牌一个数组?

The problem in your code is that your looking for 16 distinct numbers out of 15 possible values.您的代码中的问题是您要从15 个可能的值中寻找16 个不同的数字。

The reason for this is that Math.floor(Math.random() * 15) + 1;这样做的原因是Math.floor(Math.random() * 15) + 1; will only return values between 1 and 15, but your loop will run until you have 16 unique values, so you enter into an infinite loop.只会返回 1 到 15 之间的值,但您的循环将一直运行,直到您有 16 个唯一值,因此您进入了无限循环。

What you're basically trying to achieve is randomly shuffle an array with values from 1 to 16.您基本上想要实现的是随机打乱一个值为 1 到 16 的数组。

One common solution with good performance ( O(n) ) is the so-called Fisher-Yates shuffle .一种具有良好性能 ( O(n) ) 的常见解决方案是所谓的Fisher-Yates shuffle Here is code that addresses your requirements based on an implementation by Mike Bostock :以下是根据Mike Bostock实现满足您的要求的代码:

 function shuffle(array) { let m = array.length, t, i; while (m) { i = Math.floor(Math.random() * m--); t = array[m]; array[m] = array[i]; array[i] = t; } return array; } // create array with values from 1 to 16 const array = Array(16).fill().map((_, i) => i + 1); // shuffle const shuffled = shuffle(array); console.log(shuffled);

Compared to your approach and the approach of other answers to this question, the code above will only make 15 calls to the random number generator, while the others will make anywhere between 16 and an infinite number of calls (1) .与您的方法和此问题的其他答案的方法相比,上面的代码只会对随机数生成器进行 15 次调用,而其他代码将进行 16 到无限次调用(1)之间的任何地方。


(1) In probability theory, this is called the coupon collector's problem . (1)在概率论中,这称为优惠券收集者问题 For a value n of 16, on average 54 calls would have to be made to collect all 16 values.对于 16 的值n ,平均必须进行 54 次调用才能收集所有 16 个值。

Try like this :像这样尝试:

    let num = [];

function createNum () {
    for (i = 0; num.length <= 17; i++) {
        let numGen = Math.floor(Math.random() * 16) + 1;
        if (!num.includes(numGen)) {
            num.push(numGen);
        };
    };
}
console.log(createNum());
document.getElementById("selectedNumbersShownHere").innerHTML = num;
console.log(num);

Please find the working demo here请在此处找到工作演示

This is an infinite loop error. Because your loop variable "i" is always less than or equal to 15. and your i++ is inside the if statement. You can achieve it in multiple ways. Below is one sample.

let num = [];

function createNum () {
    for (i = 0; i <= 15;) {
        let numGen = Math.floor(Math.random() * 15) + 1;
        if (!num.includes(numGen)) {
            num.push(numGen);
        };
         i++;
    };
}
console.log(createNum());
document.getElementById("selectedNumbersShownHere").innerHTML = num;
console.log(num);

sorry, I'm "passionate" about this question, and I can't resist presenting a second answer, which is IMHO: the best!对不起,我对这个问题“充满热情”,我忍不住提出第二个答案,恕我直言:最好的!

 function createNum () { let num = [] for (let len=0;len<16;) { let numGen = Math.ceil(Math.random() * 16) if (!num.includes(numGen)) { len = num.push(numGen) } } return num } let unOrdered = createNum(); console.log( JSON.stringify( unOrdered ) ); /* document.getElementById("selectedNumbersShownHere").textContent = unOrdered_16_vals.join(''); */

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM