概述
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
最后
以上就是飘逸棒球为你收集整理的C#产生随机数之一 生成真随机数的全部内容,希望文章能够帮你解决C#产生随机数之一 生成真随机数所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复