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();
        }
    }
}

这里写图片描述

可以看到同是产生400个随机数,第四种方式的效率比第三种提高了1数量级,比第二种提高了3个数量级。

参考链接:
c# Random太快产生的随机数会重复

C# 生成随机数

C# 产生真随机数(RNGCryptoServiceProvider)

到底要不要用伪随机数?

  • 10
    点赞
  • 59
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值