C#产生随机数之一 生成真随机数

Random 成员
名称 ● 说明
Equals ● 确定指定的 Object 是否等于当前的 Object。(继承自 Object。) 
Finalize ● 允许Object 在“垃圾回收”回收 Object 之前尝试释放资源并执行其他清理操作。(继承自 Object。) 
GetHashCode ●用作特定类型的哈希函数。(继承自 Object。) 
GetType ● 获取当前实例的 Type。(继承自 Object。) 
Next ● 已重载。 返回随机数。 
NextBytes ● 用随机数填充指定字节数组的元素。 
NextDouble ● 返回一个介于 0.0 和 1.0 之间的随机数。 
ToString ● 返回表示当前 Object 的String。(继承自 Object。)
--------------------- 
 

Random类是一个产生伪随机数字的类,它的构造函数有两种,一个是直接New Random(),另外一个是New Random(Int32 Seed),前者是根据触发那刻的系统时间做为种子,来产生一个随机数字,后者可以自己设定触发的种子。 
New Random(Int32 Seed)一般都是用UnCheck((Int)DateTime.Now.Ticks)做为参数种子,因此如果计算机运行速度很快,如果触发Random函数间隔时间很短,就有可能造成产生一样的随机数,因为伪随机的数字,在Random的内部产生机制中还是有一定规律的,并非是真正意义上的完全随机。 

Random快速连续产生相同随机数的解决方案:

第一种方式:使用DateTime.Now.Ticks生成随机数; 
优缺点:如果触发Random函数间隔时间很短,就有可能造成产生一样的随机数 
 
第二种方式: 使用Thread.Sleep(),在每次循环产生随机数前延迟几个毫秒,防止由于计算机运算速度过快,产生伪随机数; 
优缺点:生成速度慢,不适合快速生成大量随机数 
 
第三种方式:使用RNGCryptoServiceProvider生成Seed;加密随机数生成器生成Random的Seed种子 
缺点:生成速度较慢,但是好于第二种; 
优点:使用RNGCryptoServiceProvider还可以生成随机字符串;

第四种方式:使用Guid生成Seed; 
优缺点:生成速度快,适合生成大量随机数;

以下是四种方式的源码实现:

using System;
using System.Diagnostics;
using System.Threading;

namespace CSharp生成随机数
{
    class Program
    {
        /// <summary>
        /// 使用RNGCryptoServiceProvider生成种子
        /// </summary>
        /// <returns></returns>
        static int GetRandomSeed()
        {
            byte[] bytes = new byte[4];
            System.Security.Cryptography.RNGCryptoServiceProvider rng = new System.Security.Cryptography.RNGCryptoServiceProvider();
            rng.GetBytes(bytes);
            return BitConverter.ToInt32(bytes, 0);

        }
        /// <summary>
        /// 使用Guid生成种子
        /// </summary>
        /// <returns></returns>
        static int GetRandomSeedbyGuid()
        {
            return new Guid().GetHashCode();
        }

        /// <summary>
        /// 使用Thread.Sleep()方式产生真随机数
        /// </summary>
        static void GetRandomBySleep(int[] array)
        {
            int len = array.Length;
            Random random = new Random();

            for (int i = 0; i < len; i++)
            {
                Thread.Sleep(1);
                array[i] = random.Next(0, len);
            }
            //Print(array);// 输出生成的随机数
        }
        /// <summary>
        /// 使用RNGCryptoServiceProvider产生的种子生成真随机数
        /// </summary>
        static void GetRandomByRNGCryptoServiceProvider(int[] array)
        {
            int len = array.Length;
            Random random = new Random(GetRandomSeed());
            for (int i = 0; i < len; i++)
            {

                array[i] = random.Next(0, len);
            }
            //Print(array);// 输出生成的随机数
        }
        /// <summary>
        /// 使用Guid产生的种子生成真随机数
        /// </summary>
        static void GetRandomByGuid(int[] array)
        {
            int len = array.Length;
            Random random = new Random(GetRandomSeedbyGuid());
            for (int i = 0; i < len; i++)
            {
                array[i] = random.Next(0, len);
            }
            //Print(array);// 输出生成的随机数
        }
        static void Print(int[] array)
        {
            for (int i = 0; i < array.Length; i++)
                Console.Write(string.Format("{0} ", array[i]));
            Console.ReadLine();
        }
        static void Main(string[] args)
        {
            int[] array = new int[400];
            Stopwatch sw = new Stopwatch();

            sw.Start();
            GetRandomBySleep(array);
            sw.Stop();
            TimeSpan ts = sw.Elapsed;
            Console.WriteLine("使用Thread.Sleep(1)总共花费{0}ms.", ts.TotalMilliseconds);
            sw.Reset();

            sw.Start();
            GetRandomByRNGCryptoServiceProvider(array);
            sw.Stop();
            ts = sw.Elapsed;
            Console.WriteLine("使用RNGCryptoServiceProvider生成种子,产生随机数总共花费:{0}ms.", ts.TotalMilliseconds);
            sw.Reset();

            sw.Start();
            GetRandomByGuid(array);
            sw.Stop();
            ts = sw.Elapsed;
            Console.WriteLine("使用Guid生成种子,产生随机数总共花费:{0}ms.", ts.TotalMilliseconds);

            Console.ReadLine();
        }
    }
}



五、唯一时间戳ID生成的代码算法,借鉴了点雪花算法:

 /// <summary>
    /// 时间戳ID
    /// </summary>
    public class TimestampID
    {
        private long _lastTimestamp;
        private long _sequence; //计数从零开始
        private readonly DateTime? _initialDateTime;
        private static TimestampID _timestampID;
        private const int MAX_END_NUMBER = 9999;

        private TimestampID(DateTime? initialDateTime)
        {
            _initialDateTime = initialDateTime;
        }

        /// <summary>
        /// 获取单个实例对象
        /// </summary>
        /// <param name="initialDateTime">最初时间,与当前时间做个相差取时间戳</param>
        /// <returns></returns>
        public static TimestampID GetInstance(DateTime? initialDateTime = null)
        {
            if (_timestampID == null) Interlocked.CompareExchange(ref _timestampID, new TimestampID(initialDateTime), null);
            return _timestampID;
        }

        /// <summary>
        /// 最初时间,作用时间戳的相差
        /// </summary>
        protected DateTime InitialDateTime
        {
            get
            {
                if (_initialDateTime == null || _initialDateTime.Value == DateTime.MinValue) return new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
                return _initialDateTime.Value;
            }
        }
        /// <summary>
        /// 获取时间戳ID
        /// </summary>
        /// <returns></returns>
        public string GetID()
        {
            long temp;
            var timestamp = GetUniqueTimeStamp(_lastTimestamp, out temp);
            return $"{timestamp}{Fill(temp)}";
        }

        private string Fill(long temp)
        {
            var num = temp.ToString();
            IList<char> chars = new List<char>();
            for (int i = 0; i < MAX_END_NUMBER.ToString().Length - num.Length; i++)
            {
                chars.Add('0');
            }
            return new string(chars.ToArray()) + num;
        }

        /// <summary>
        /// 获取一个时间戳字符串
        /// </summary>
        /// <returns></returns>
        public long GetUniqueTimeStamp(long lastTimeStamp, out long temp)
        {
            lock (this)
            {
                temp = 1;
                var timeStamp = GetTimestamp();
                if (timeStamp == _lastTimestamp)
                {
                    _sequence = _sequence + 1;
                    temp = _sequence;
                    if (temp >= MAX_END_NUMBER)
                    {
                        timeStamp = GetTimestamp();
                        _lastTimestamp = timeStamp;
                        temp = _sequence = 1;
                    }
                }
                else
                {
                    _sequence = 1;
                    _lastTimestamp = timeStamp;
                }
                return timeStamp;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        private long GetTimestamp()
        {
            if (InitialDateTime >= DateTime.Now) throw new Exception("最初时间比当前时间还大,不合理");
            var ts = DateTime.UtcNow - InitialDateTime;
            return (long)ts.TotalMilliseconds;
        }
    }

注意:本内容来自:https://blog.csdn.net/cjolj/article/details/59484045

                                https://blog.csdn.net/qq_21736559/article/details/72770666


 

猜你喜欢

转载自blog.csdn.net/xiaochenXIHUA/article/details/89574431