如何生成一组不重复的随机数

问题:生成随机数的方法有很多,如利用 C# 中的 Random 类中 Next() 方法就可以生成。但是这样生成的随机数有可能会重复,如果需要生成不同的随机数,有没有相应的高效的方法呢?

分析:1.获取生成随机数的方法,这里用 Next 方法

        2.在生成随机数之后立刻判断它是否与之前生成的重复,如果重复则重新生成,否则继续生成下一个

        3.优化循环语句

C#代码:

using System;
using System.Threading;

namespace MyTest
{
    public class Program
    {
        static void Main(string[] args)
        {
            //随机数的个数
            int count = 100;
            int[] data1 = new int[count];
            int[] data2 = new int[count];

            //调用不同的方法,产生随机数
            Program pro = new Program();
            //产生随机数的方法一
            data1 = pro.GetRandomData1(count);
            //输出随机数
            System.Console.Write("方法一产生了 {0} 个随机数:\r\n", count);
            System.Console.Write(string.Join(" ", data1) + "\r\n");
            //产生随机数的方法二
            data2 = pro.GetRandomData2(count);
            //输出随机数
            System.Console.Write("方法二产生了 {0} 个随机数:\r\n", count);
            System.Console.Write(string.Join(" ", data2) + "\r\n");

            //产生随机字符串
            System.Console.Write("产生了 10 个随机字符串:\r\n");
            for (int i = 0; i < 10; i++)
            {
                System.Console.Write("{0}\r\n", pro.GetRandomStr(4));
                //产生一个随机字符串后,线程停顿1毫秒,防止重复
                Thread.Sleep(1);
            }

            System.Console.ReadKey();
        }

        /// <summary>
        /// 功能:产生不同的随机数,方法一
        /// 特点:和 GetRandomDatas2 方法相比,空间上节省了一个数组,但时间效率很低
        /// </summary>
        /// <param name="count">随机数的个数</param>
        /// <returns>产生的所有随机数</returns>
        public int[] GetRandomData1(int count)
        {
            int data = 0;
            int[] arr = new int[count];
            Random rand = new Random();

            //产生N个不同的随机数
            for (int i = 0; i < count; i++)
            {
                data = rand.Next(0, count);
                //检测当前随机数是否在之前出现过
                for (int j = 0; j < i; j++)
                {
                    //如果之前出现过,则重新产生随机数,并重新检测
                    if (arr[j] == data)
                    {
                        data = rand.Next(0, count);
                        j = -1;
                    }
                }
                //如果之前未出现,则保存当前随机数
                arr[i] = data;
            }
            return arr;
        }

        /// <summary>
        /// 功能:产生不同的随机数,方法二
        /// 特点:和 GetRandomDatas1 方法相比,时间效率高很多,但多用了一个数组boo[],空间开销较大
        /// 适用范围:该方法只适用产生 “整数” 的随机数的问题,不适用产生非整数随机数:小数、负数等
        /// </summary>
        /// <param name="count">随机数的个数</param>
        /// <returns>产生的所有随机数</returns>
        public int[] GetRandomData2(int count)
        {
            int data = 0;
            int[] arr = new int[count];
            bool[] boo = new bool[count];
            Random rand = new Random();

            for (int i = 0; i < count; i++)
            {
                do
                {
                    // 如果产生的数相同继续循环
                    data = rand.Next(count);
                }
                while (boo[data]);

                boo[data] = true;
                arr[i] = data;
            }
            return arr;
        }

        /// <summary>
        /// 附加功能:产生一个随机纯数字的字符串(如:验证码,也可以直接用 rand.Next(int minValue, int maxValue) 产生)
        /// 问题:如果产生两个随机字符串的时间间隔太短,有可能会出现重复的字符串
        /// </summary>
        /// <param name="strLength"></param>
        /// <returns></returns>
        private string GetRandomStr(int strLength)
        {
            string randomStr = "";
            int temp = -1;
            char[] allChars = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
            Random rand = new Random();

            for (int i = 0; i < strLength; i++)
            {
                if (temp != -1)
                {
                    rand = new Random(i * temp * ((int)DateTime.Now.Ticks));
                }
                int t = rand.Next(allChars.Length);
                if (temp == t)
                {
                    return GetRandomStr(strLength);
                }
                temp = t;
                randomStr += allChars[t];
            }
            return randomStr;
        }
    }
}

运行结果:

方法一产生了 100 个随机数:

80 29 14 60 8 33 66 65 93 55 15 ...

方法而产生了 100 个随机数:

80 29 14 60 8 33 66 65 93 55 15 ...

产生了 10 个随机字符串:

8781

1957

1342

1528

1351

...

posted on 2016-07-14 11:06  wangzhiliang  阅读(6417)  评论(0编辑  收藏  举报

导航