zoukankan      html  css  js  c++  java
  • Random快速产生相同随机数的原因及解决方案

    老生常谈,还是那三句话:

    学历代表你的过去,能力代表你的现在,学习代表你的将来

    十年河东,十年河西,莫欺少年穷

    学无止境,精益求精

    问题描述:很多时候我们可能需要在极短的时间内生成大量的随机数,但是你可能会发现生成了很多重复的随机数。并不是你所希望生成大量不同的数,或者说相同的数极少。

    分析原因:Random是主要产生伪随机数的类,它主要包括两个构造函数(无参构造函数和带一个Int32类型参数的构造函数),无参构造函数主要采用系统时间作为随机种子,带参数的构造函数需要自己去指定随机种子。而在很短的时间内生成大量随机数的时候,由于时间相当短暂,很大的可能性一部分随机数生成时,取到作为随机种子的系统时间相同,因此产生出来的随机数就相同了。

    解决方案:既然知道原因何在了,解决方案就可以出来了。要生成不同的随机数,我们只需要保证随机种子尽可能不重复(不能完全保证不重复)即可。Random类有两个构造函数,我们就可以考虑用两种方法去解决这个问题。(有更好、更多的解决办法的朋友,告诉我一声了,呵呵~~)

    1. 利用无参构造函数,既然它是采用系统时间作为随机种子,而取到的系统时间相同,才造成生成了重复的随机数,因此我们可以在生成一个随机数后延时一段时间,让它下次不取到相同的系统时间,这样随机种子也就不相同了。延时可以考虑使用Thread.Sleep(100),这里是延时0.1秒。
    2. 利用带参构造函数,我们想办法去生成尽可能不重复的随机种子。注意到MSDN中介绍Random.NextBytes()方法时,有这样一句话“要生成适合于创建随机密码的加密安全随机数,请使用如 RNGCryptoServiceProvider.GetBytes 这样的方法。”,它包含的意义是微软已经有现成的东西生成随机的密码,那我们就可以拿来用用了。我们就用它来生成我们的随机种子。

       可以写一个生成随机种子的方法,代码如下:

    在此,贴下用法:

            public int GetRandSeed()
            {
                byte[] bytes = new byte[8];
                System.Security.Cryptography.RNGCryptoServiceProvider rng = new System.Security.Cryptography.RNGCryptoServiceProvider();
                rng.GetBytes(bytes);
                return BitConverter.ToInt32(bytes, 0);
            }

    然后再贴出一个具体应用。

    生成固定前缀的身份证号(北京市市辖区身份证开头 110100):

    #region 生成身份证号
            /// <summary>
            /// 身份证后四位
            /// </summary>
            /// <param name="codeLength"></param>
            /// <returns></returns>
            /// 
            private  string GetCode(int codeLength)
            {
                Random rand = new Random();
                string so = "1,2,3,4,5,6,7,8,9,0";
                string[] strArr = so.Split(',');
                string code = "";
                for (int i = 0; i < codeLength; i++)
                {
                    code += strArr[rand.Next(0, strArr.Length)];
                }
                return code;
            }
    
            private string GetCodeForIdNo()
            {
                byte[] bytes = new byte[8];
                System.Security.Cryptography.RNGCryptoServiceProvider rng = new System.Security.Cryptography.RNGCryptoServiceProvider();
                rng.GetBytes(bytes);
                int j = Math.Abs(BitConverter.ToInt32(bytes, 0));
                if (j.ToString().Length == 1)
                {
                    return GetCode(3) + j.ToString();
                }
                else if (j.ToString().Length == 2)
                {
                    return GetCode(2) + j.ToString();
                }
                else if (j.ToString().Length == 3)
                {
                    return GetCode(1) + j.ToString();
                }
                else if (j.ToString().Length == 4)
                {
                    return j.ToString();
                }
                else
                {
                    return j.ToString().Substring(0,4);
                }
            }
    
            public List<IdCard> CreateIdCard()
            {
                string CardFrist = "110100";//北京市市区
                List<IdCard> CMlist = new List<IdCard>();
                int Year = 1955;
                List<int> YearList = new List<int>();//年份范围
                List<int> monthList = new List<int>();//月份范围
                List<int> dayList = new List<int>();//天范围
                for (int i = -35; i < 36; i++)
                {
                    YearList.Add(Year + i);
                }
    
                for (int i = 1; i < 13; i++)
                {
                    monthList.Add(i);
                }
                //不考虑瑞年非闰年及月份的天数 最大28天
                for (int i =1; i < 29; i++)
                {
                    dayList.Add(i);
                }
                //dd  
                XiCard(YearList); XiCard(monthList); XiCard(dayList);
                for (int i = 0; i < 100; i++)
                {
                    IdCard CM = new IdCard();
                    int Y_Len=YearList.Count;
                    int M_Len=monthList.Count;
                    int D_Len=dayList.Count;
                    int Nyear = YearList[i % Y_Len];
                    int Nmonth = monthList[i % M_Len];
                    int Nday = dayList[i % D_Len];
                    if (Nmonth < 10&&Nday<10)
                    {
                        CM.BrithDay = Convert.ToDateTime(Nyear.ToString() + "-0" + Nmonth.ToString() + "-0" + Nday.ToString());
                        CM.IdNo = CardFrist + CM.BrithDay.ToString("yyyyMMdd") + GetCodeForIdNo();
                        CMlist.Add(CM);
                    }
                    if (Nmonth < 10 && Nday > 10)
                    {
                        CM.BrithDay = Convert.ToDateTime(Nyear.ToString() + "-0" + Nmonth.ToString() + "-" + Nday.ToString());
                        CM.IdNo = CardFrist + CM.BrithDay.ToString("yyyyMMdd") + GetCodeForIdNo();
                        CMlist.Add(CM);
                    }
                    if (Nmonth > 10 && Nday > 10)
                    {
                        CM.BrithDay = Convert.ToDateTime(Nyear.ToString() + "-" + Nmonth.ToString() + "-" + Nday.ToString());
                        CM.IdNo = CardFrist + CM.BrithDay.ToString("yyyyMMdd") + GetCodeForIdNo();
                        CMlist.Add(CM);
                    }
                    if (Nmonth > 10 && Nday < 10)
                    {
                        CM.BrithDay = Convert.ToDateTime(Nyear.ToString() + "-" + Nmonth.ToString() + "-0" + Nday.ToString());
                        CM.IdNo = CardFrist + CM.BrithDay.ToString("yyyyMMdd") + GetCodeForIdNo();
                        CMlist.Add(CM);
                    }
    
                }
                return CMlist;
            }
    
            /// <summary>
            /// dd
            /// </summary>
            /// <param name="list"></param>
            private void XiCard(List<int> list)
            {
                int i = list.Count;
                int j;
                if (i == 0)
                {
                    return;
                }
                while (--i != 0)
                {
                    Random ran = new Random();
                    j = ran.Next() % (i + 1);
                    int tmp = list[i];
                    list[i] = list[j];
                    list[j] = tmp;
                }
            }
            #endregion

    Model 很简单,如下:

        public class IdCard
        {
            public string IdNo { get; set; }
            public DateTime BrithDay { get; set; }
        }

    测试如下:

    @陈卧龙的博客

  • 相关阅读:
    Stock Transfer I
    Negative Stock in "Stock in Transit"
    ZFINDEXITS
    Plan Driven Procurement III: Classic Scenario in SRM 5.0
    C++builder 创建进程之CreateProcess函数
    常用DOS命令
    【转】程序员的几个级别
    几本书
    OOP SOLID原则
    SSRS 使用总结
  • 原文地址:https://www.cnblogs.com/chenwolong/p/Random.html
Copyright © 2011-2022 走看看