生成随机,唯一的值C#

问题描述 投票:25回答:12

我已经搜索了一段时间并且一直在努力寻找这个,我正在尝试生成几个随机的,唯一的数字是C#。我正在使用System.Random,我正在使用DateTime.Now.Ticks种子:

public Random a = new Random(DateTime.Now.Ticks.GetHashCode());
private void NewNumber()
{
    MyNumber = a.Next(0, 10);
}

我经常给NewNumber()打电话,但问题是我经常会重复数字。有些人建议因为我每次都是随机声明它,它不会产生随机数,所以我把声明放在我的函数之外。有什么建议或比使用System.Random更好的方法?谢谢

c# .net random unique
12个回答
23
投票

我经常给NewNumber()打电话,但问题是我经常会重复数字。

Random.Next不保证这个数字是唯一的。您的范围也是0到10,您可能会获得重复值。也许你可以设置一个int列表,并在检查它是否包含副本后在列表中插入随机数。就像是:

public Random a = new Random(); // replace from new Random(DateTime.Now.Ticks.GetHashCode());
                                // Since similar code is done in default constructor internally
public List<int> randomList = new List<int>();
int MyNumber = 0;
private void NewNumber()
{
    MyNumber = a.Next(0, 10);
    if (!randomList.Contains(MyNumber))
        randomList.Add(MyNumber);
}

-1
投票

random Number函数返回0到100000之间的唯一整数值

  bool check[] = new bool[100001];
  Random r = new Random();
  public int randomNumber() {
      int num = r.Next(0,100000);
       while(check[num] == true) {
             num = r.Next(0,100000);
     }
    check[num] = true;
   return num;
 }

-1
投票

在这里,我发布了一个视频,它解释了如何生成唯一的随机数

  public List<int> random_generator(){

  Random random = new Random();

   List<int> random_container = new List<int>;

     do{

       int random_number = random.next(10);

      if(!random_container.contains(random_number){

       random_container.add(random_number)
  }
}
   while(random_container.count!=10);


     return random_container; 
  }

这里,,,在随机容器中你会得到非重复的10个数字从0到9(10个数字)开始随机..谢谢........


-2
投票

您可以使用C#的基本随机函数

Random ran = new Random();
int randomno = ran.Next(0,100);

你现在可以在randomno中使用你想要的任何值,但请记住,这将在0100之间生成一个随机数,你可以将它扩展到任何数字。


-4
投票

试试这个:

private void NewNumber()
  {
     Random a = new Random(Guid.newGuid().GetHashCode());
     MyNumber = a.Next(0, 10);
  }

一些解释:

Guidbase on here:表示全局唯一标识符(GUID)

Guid.newGuid()生成一个独特的标识符,如"936DA01F-9ABD-4d9d-80C7-02AF85C822A8"

它将在整个宇宙base on here独特

散列码here从我们的唯一标识符生成唯一的整数

所以Guid.newGuid().GetHashCode()给了我们一个唯一的数字,随机类将产生真正的随机数抛出这个


16
投票

如果范围仅为0到9,您可以尝试改组可能的整数数组。这增加了避免数字生成中的任何冲突的好处。

var nums = Enumerable.Range(0, 10).ToArray();
var rnd = new Random();

// Shuffle the array
for (int i = 0;i < nums.Length;++i)
{
    int randomIndex = rnd.Next(nums.Length);
    int temp = nums[randomIndex];
    nums[randomIndex] = nums[i];
    nums[i] = temp;
}

// Now your array is randomized and you can simply print them in order
for (int i = 0;i < nums.Length;++i)
    Console.WriteLine(nums[i]);

10
投票

注意,我不推荐这个:)。这里也是一个“oneliner”:

//This code generates numbers between 1 - 100 and then takes 10 of them.
var result = Enumerable.Range(1,101).OrderBy(g => Guid.NewGuid()).Take(10).ToArray();

9
投票

我发布了一个正确的shuffle算法实现,因为这里发布的另一个不会产生统一的shuffle。

正如另一个答案所述,对于要随机化的少量值,您可以简单地用这些值填充数组,对数组进行混洗,然后使用您想要的许多值。

以下是Fisher-Yates Shuffle(又名Knuth Shuffle)的实现。 (阅读该链接的“实现错误”部分(搜索“始终在每次迭代中从整个有效数组索引范围中选择j”),以查看有关此处发布的其他实现有什么问题的讨论。)

using System;
using System.Collections.Generic;

namespace ConsoleApplication2
{
    static class Program
    {
        static void Main(string[] args)
        {
            Shuffler shuffler = new Shuffler();
            List<int> list = new List<int>{ 1, 2, 3, 4, 5, 6, 7, 8, 9 };
            shuffler.Shuffle(list);

            foreach (int value in list)
            {
                Console.WriteLine(value);
            }
        }
    }

    /// <summary>Used to shuffle collections.</summary>

    public class Shuffler
    {
        /// <summary>Creates the shuffler with a <see cref="MersenneTwister"/> as the random number generator.</summary>

        public Shuffler()
        {
            _rng = new Random();
        }

        /// <summary>Shuffles the specified array.</summary>
        /// <typeparam name="T">The type of the array elements.</typeparam>
        /// <param name="array">The array to shuffle.</param>

        public void Shuffle<T>(IList<T> array)
        {
            for (int n = array.Count; n > 1; )
            {
                int k = _rng.Next(n);
                --n;
                T temp = array[n];
                array[n] = array[k];
                array[k] = temp;
            }
        }

        private System.Random _rng;
    }
}

2
投票

检查这个随时可用的方法:提供您想要获得的范围和数量。

public static int[] getUniqueRandomArray(int min, int max, int count) {
    int[] result = new int[count];
    List<int> numbersInOrder = new List<int>();
    for (var x = min; x < max; x++) {
        numbersInOrder.Add(x);
    }
    for (var x = 0; x < count; x++) {
        var randomIndex = Random.Range(0, numbersInOrder.Count);
        result[x] = numbersInOrder[randomIndex];
        numbersInOrder.RemoveAt(randomIndex);
    }

    return result;
}

1
投票

根据您的真实情况,您可以执行以下操作:

using System;
using System.Collections.Generic;
using System.Linq;

namespace SO14473321
{
    class Program
    {
        static void Main()
        {
            UniqueRandom u = new UniqueRandom(Enumerable.Range(1,10));
            for (int i = 0; i < 10; i++)
            {
                Console.Write("{0} ",u.Next());
            }
        }
    }

    class UniqueRandom
    {
        private readonly List<int> _currentList;
        private readonly Random _random = new Random();

        public UniqueRandom(IEnumerable<int> seed)
        {
            _currentList = new List<int>(seed);
        }

        public int Next()
        {
            if (_currentList.Count == 0)
            {
                throw new ApplicationException("No more numbers");
            }

            int i = _random.Next(_currentList.Count);
            int result = _currentList[i];
            _currentList.RemoveAt(i);
            return result;
        }
    }
}

0
投票

在这里我的版本使用HashSet查找N个随机唯一数字。看起来很简单,因为HashSet只能包含不同的项目。有趣的是 - 它会比使用List或Shuffler更快吗?

using System;
using System.Collections.Generic;

namespace ConsoleApplication1
{
    class RnDHash
    {
        static void Main()
        {
            HashSet<int> rndIndexes = new HashSet<int>();
            Random rng = new Random();
            int maxNumber;
            Console.Write("Please input Max number: ");
            maxNumber = int.Parse(Console.ReadLine());
            int iter = 0;
            while (rndIndexes.Count != maxNumber)
            {
                int index = rng.Next(maxNumber);
                rndIndexes.Add(index);
                iter++;
            }
            Console.WriteLine("Random numbers were found in {0} iterations: ", iter);
            foreach (int num in rndIndexes)
            {
                Console.WriteLine(num);
            }
            Console.ReadKey();
        }
    }
}

0
投票

我注意到接受的答案一直在列表中添加int并继续使用if (!randomList.Contains(MyNumber))检查它们,我认为这不能很好地扩展,特别是如果你不断要求新的数字。

我会做相反的事情。

  1. 在线路启动时生成列表
  2. 从列表中获取随机索引
  3. 从列表中删除找到的int

这需要稍微多一点的启动时间,但会扩展得更好。

public class RandomIntGenerator
{
    public Random a = new Random();
    private List<int> _validNumbers;

    private RandomIntGenerator(int desiredAmount, int start = 0)
    {
        _validNumbers = new List<int>();
        for (int i = 0; i < desiredAmount; i++)
            _validNumbers.Add(i + start);
    }

    private int GetRandomInt()
    {
        if (_validNumbers.Count == 0)
        {
            //you could throw an exception here
            return -1;
        }
        else
        {
            var nextIndex = a.Next(0, _validNumbers.Count - 1);
            var number    = _validNumbers[nextIndex];
            _validNumbers.RemoveAt(nextIndex);
            return number;
        }
    }
}

-1
投票

您还可以使用存储每个随机值的dataTable,然后在dataColumn中使用!= values时执行随机方法

© www.soinside.com 2019 - 2024. All rights reserved.