C# 非重复随机数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1011198/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 05:29:24  来源:igfitidea点击:

Non-repetitive random number

c#random

提问by web dunia

To generate Random numbers from 1- 20 I need to pick selective and it should not be repetitive.

要从 1-20 生成随机数,我需要选择有选择性的,并且不应该是重复的。

How to do this in C#

如何在 C# 中做到这一点

Note I need to loop through as like this

注意我需要像这样循环

Random rnd = new Random()
rnd.Next(1,20)
for(int i =0; i<=20;i++)
{

}

For all the loops number should be 1 to 20

对于所有循环数应为 1 到 20

回答by Jon Skeet

What exactly do you mean by "should not be repetitive"? If you mean that you don't want to get anyduplicates, then you should basically take a list of the numbers 1-20, shuffle them, and then grab one at a time from the head of the list. For an efficient way to shuffle a list, see this Stack Overflow answer.

“不应重复”究竟是什么意思?如果你的意思是你不想得到任何重复,那么你基本上应该拿一个数字 1-20 的列表,将它们随机排列,然后从列表的头部一次抓取一个。有关对列表进行洗牌的有效方法,请参阅此 Stack Overflow 答案

If you just mean that your current attempt gives 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2 etc then chances are you're creating a new instance of Randomeach time you pick a number: don't do that. Each time you create an instance, it will use the current time as the "seed" for the random number generator (unless you specify one explicitly). That means if you create several instances in quick succession, each will get the same seed and therefore give the same sequence of numbers.

如果你只是说你当前的尝试给出了 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2 等那么机会是Random每次选择一个数字时,您都会创建一个新实例:不要那样做。每次创建实例时,它都会使用当前时间作为随机数生成器的“种子”(除非您明确指定一个)。这意味着如果您快速连续创建多个实例,每个实例将获得相同的种子,因此给出相同的数字序列。

Instead, use a single instance of Randomand reuse it. (Note that it's not thread-safe though, which is a pain.) For instance:

相反,使用单个实例Random并重用它。(请注意,它不是线程安全的,这很痛苦。)例如:

private static readonly Random Rng = new Random();

public int NextNumber()
{
    return Rng.Next(20) + 1;
}

That won't be thread-safe, but let us know if that's a problem. An alternative is sometimes to pass the Randominto the method (which would normally be more complicated, of course):

这不是线程安全的,但如果这有问题,请告诉我们。有时,另一种方法是将 传递Random到方法中(当然,这通常会更复杂):

public int NextNumber(Random rng)
{
    return rng.Next(20) + 1;
}

then the caller can reuse the instance appropriately.

然后调用者可以适当地重用该实例。

If you want a thread-safe way of generating random numbers, you might want to look at my StaticRandomclass in MiscUtil.

如果您想要一种生成随机数的线程安全方式,您可能需要查看我StaticRandomMiscUtil 中的类。

(Note that using rng.Next(1, 21)would also work fine - I happen to prefer the version above as I think it reduces the guesswork about inclusive/exclusive boundaries, but it's a matter of personal taste.)

(请注意,使用rng.Next(1, 21)也可以正常工作 - 我碰巧更喜欢上面的版本,因为我认为它减少了对包含/排除边界的猜测,但这是个人品味的问题。)

回答by Ahmed Said

From MSDN

来自 MSDN

"One way to improve randomness is to make the seed value time-dependent."

“提高随机性的一种方法是使种子值与时间相关。”

Another fact

另一个事实

you should "create one Random to generate many random numbers over time." This will enhance the random generation

您应该“创建一个 Random 以随时间生成许多随机数”。这将增强随机生成

回答by Hallgrim

This method will generate all the numbers, and no numbers will be repeated:

此方法将生成所有数字,并且不会重复任何数字:

/// <summary>
/// Returns all numbers, between min and max inclusive, once in a random sequence.
/// </summary>
IEnumerable<int> UniqueRandom(int minInclusive, int maxInclusive)
{
    List<int> candidates = new List<int>();
    for (int i = minInclusive; i <= maxInclusive; i++)
    {
        candidates.Add(i);
    }
    Random rnd = new Random();
    while (candidates.Count > 0)
    {
        int index = rnd.Next(candidates.Count);
        yield return candidates[index];
        candidates.RemoveAt(index);
    }
}

You can use it like this:

你可以这样使用它:

Console.WriteLine("All numbers between 0 and 20 in random order:");
foreach (int i in UniqueRandom(0, 20)) {
    Console.WriteLine(i);
}

回答by Chris Dunaway

I did one this way awhile back. I don't know how it compares to the other methods presented as far as efficiency, randomness, etc. But it seems to work:

不久前我就这样做了。我不知道它在效率、随机性等方面与其他方法相比如何。但它似乎有效:

List<int> integers = new List<int>() { 1, 2, 3, 4, 5, 6,7, 8, 9, 10, 11, 12 };

Random rnd = new Random();

var ints = from i in integers
           orderby rnd.Next(integers.Count)
           select i;

回答by Ohad Schneider

An IEnumerableimplementation, based on Hallgrim'sanswer:

一个IEnumerable实现,基于Hallgrim 的回答:

public class UniqueRandoms : IEnumerable<int>
{
    Random _rand = new Random();
    List<int> _candidates;

    public UniqueRandoms(int maxInclusive)
        : this(1, maxInclusive)
    { }

    public UniqueRandoms(int minInclusive, int maxInclusive)
    {
        _candidates = 
            Enumerable.Range(minInclusive, maxInclusive - minInclusive + 1).ToList();
    }

    public IEnumerator<int> GetEnumerator()
    {
        while (_candidates.Count > 0)
        {
            int index = _rand.Next(_candidates.Count);
            yield return _candidates[index];
            _candidates.RemoveAt(index);
        }
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

回答by Pradeep Ly

class Program
{
    static void Main(string[] args)
    {        
        List<int> list = new List<int>();
        int val;
        Random r;
        int IntialCount = 1;
        int count = 7 ;
        int maxRandomValue = 8;

        while (IntialCount <= count)
        {
            r = new Random();
            val = r.Next(maxRandomValue);
            if (!list.Contains(val))
            {
                list.Add(val);
                IntialCount++;
            }

        } 
    }
}

回答by Adel

The following way is very good way, I use a string over here, you can change the type of the list to whatever you want..., try it:

下面这个方法很好,我这里用的是字符串,你可以把列表的类型改成你想要的……,试试看:

            List<string> NamesList = new List<string>() { "Name1", "Name2", "Name3", "Name4", "Name5" };
            Random rnd = new Random();
            //Now to get random of the above "Without Repeating.."
            for (int i = 0; i <= NamesList.Count - 1; i++)
            {
                int TheSelectedRand = rnd.Next(NamesList.Count);
                string MyRandNumber = NamesList[TheSelectedRand];

                //Print or use your item here

                NamesList.Remove(NamesList[TheSelectedRand]);
            }

回答by Meisam

blow code generates 65 unique random number between 0 - 92 and return that unique random numbers in an array.

打击代码生成 0 - 92 之间的 65 个唯一随机数,并在数组中返回该唯一随机数。

public static int[] RandomNumbers_Supplier()
        {
            Random R = new Random();
            int[] RandomNumbers = new int[65];
            int k = 0, Temp;
            bool IsRepetitive = false;
            while (k < 65)
            {
                Temp = R.Next(0, 92);
                for (int i = 0; i < 65; i++)
                {
                    IsRepetitive = false;
                    if (RandomNumbers[i] == Temp)
                    {
                        IsRepetitive = true;
                        break;
                    }                    
                }
                if (!IsRepetitive)
                {
                    RandomNumbers[k] = Temp;
                    k++;
                }
            }
            return(RandomNumbers)
        }

回答by whiteCode

static void Main(string[] args)
{
    //Randomize 15 numbers out of 25 - from 1 to 25 - in ascending order
    var randomNumbers = new List<int>();
    var randomGenerator = new Random();
    int initialCount = 1;

    for (int i = 1; i <= 15; i++)
    {
        while (initialCount <= 15)
        {
            int num = randomGenerator.Next(1, 26);
            if (!randomNumbers.Contains(num))
            {
                randomNumbers.Add(num);
                initialCount++;
            }
        }
    }
    randomNumbers.Sort();
    randomNumbers.ForEach(x => Console.WriteLine(x));
}