生成真隨機數(綜合轉載)

清新悅悠然發表於2018-06-29

1、直接用.NET Framework 提供的 Guid() 函式,此種方法使用非常廣泛。GUID(全域性統一識別符號)是指在一臺機器上生成的數字,它保證對在同一時空中的任何兩臺計算機都不會生成重複的 GUID 值(即保證所有機器都是唯一的)。關於GUID的介紹在此不作具體熬述,想深入瞭解可以自行查閱MSDN。程式碼如下:

複製程式碼 程式碼如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string _guid = GetGuid();
Console.WriteLine(“唯一碼:{0}\t長度為:{1}\n去掉連線符:{2}”, _guid, _guid.Length, _guid.Replace(“-“, “”));

        string uniqueIdString = GuidTo16String();
        Console.WriteLine("唯一碼:{0}\t長度為:{1}", uniqueIdString, uniqueIdString.Length);

        long uniqueIdLong = GuidToLongID();
        Console.WriteLine("唯一碼:{0}\t長度為:{1}", uniqueIdLong, uniqueIdLong.ToString().Length);

    }

    /// <summary>
    /// 由連字元分隔的32位數字
    /// </summary>
    /// <returns></returns>
    private static string GetGuid()
    {
        System.Guid guid = new Guid();
        guid = Guid.NewGuid();
        return guid.ToString();
    }

    /// <summary>  
    /// 根據GUID獲取16位的唯一字串  
    /// </summary>  
    /// <param name=\"guid\"></param>  
    /// <returns></returns>  
    public static string GuidTo16String()
    {
        long i = 1;
        foreach (byte b in Guid.NewGuid().ToByteArray())
            i *= ((int)b + 1);

        return string.Format("{0:x}", i - DateTime.Now.Ticks);
    }

    /// <summary>  
    /// 根據GUID獲取19位的唯一數字序列  
    /// </summary>  
    /// <returns></returns>  
    public static long GuidToLongID()
    {
        byte[] buffer = Guid.NewGuid().ToByteArray();
        return BitConverter.ToInt64(buffer, 0);
    }   

}

}

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
{
///
/// 使用RNGCryptoServiceProvider生成種子
///
///
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個數量級。

相關文章