[英]What internal algorithm does C# use to generate random number using Next method of Random class instance?
[英]C# Generate random numbers, while using library, that use internal Random instance
為了確保不同的隨機數,您應該僅使用Random
類的一個實例,如此處 , 此處和此處的答案所建議。
在我的庫中,我需要隨機數,因此我創建了一個類Randomizer
,該類提供了使用單個Random
實例返回隨機數的方法。 這是Randomizer
代碼的一部分:
class Randomizer
{
private Randomizer() { }
public static Randomizer Instance { get; } = new Randomizer();
private static readonly Random random = new Random();
private static readonly object syncLock = new object();
public int Next(int minValue, int maxValue)
{
lock(syncLock)
{
return random.Next(minValue, maxValue);
}
}
// rest of code
}
現在,如果我的圖書館用戶也需要隨機數怎么辦? 我應該公開我的Randomizer
類並在庫的文檔中指定用戶應該使用我的Randomizer
類來生成隨機數嗎?
為了確保不同的隨機數,您應該只使用Random類的一個實例
那不是很正確。 創建多個Random
實例非常好,只要您不要在緊湊的循環中初始化它們(因為它們是在當前時間播種的,因此您希望實例化時每個實例的當前時間都不同) 。
當您創建一個僅創建一個Random
對象並重用它的靜態類時,就可以了。 從理論上講,您的庫的調用者可以創建自己的靜態Random
,該靜態Random
是同時創建的,因此它們的生成器將與您的生成器獲得相同的種子,並因此獲得相同的隨機數序列。 由於創建靜態類需要花費時間,因此可能不會發生。 除非有一定的原因,否則在呼叫者的序列和您的序列之間的相關性很重要,反正這也可能無關緊要。
您為什么要用自己的實現負擔圖書館的使用者?
如果它是內部的,因為您需要一個非常特定的隨機提供程序來提供庫的內部運行。 如果在與庫交互時不需要外部使用者也遵守您在代碼中強加的規則,則不要公開生成器,如果需要的話,讓用戶使用自己的Random
。
另一方面,如果您需要使用者在與庫的公共API交互時使用特定的隨機數生成器,則需要公開公開該類。
通過使用保證為隨機的顯式種子(例如,從操作系統中獲取一個)來初始化您的Random對象。 這樣,用戶是否創建自己的Random實例都沒有關系,並且您無需考慮將對Next
方法的調用與用戶代碼進行同步。
但是,如果您無法獲得隨機種子,則一種解決方案是定義一個接口,並讓您的庫用戶向需要隨機數的每個組件注入一個實例:
public interface IRandomizer
{
int Next(int minValue, int maxValue);
}
該接口的約定必須定義您的庫的確切需求(例如, Next
方法必須是線程安全的)。 您的Randomizer類可以實現此接口,以用作默認實現。
例如,密鑰生成器庫組件可以提供兩個構造函數:
public class KeyGenerator
{
private IRandomizer randomizer;
public KeyGenerator(IRandomizer randomizer)
{
// instance will use the specified IRandomizer
this.randomizer = randomizer;
}
public KeyGenerator()
{
// instance will use your Randomizer class.
this.randomizer = Randomizer.Instance;
}
}
這樣,您的圖書館用戶就可以決定是要提供自己的隨機數生成器,還是要使用圖書館的默認值。
我將使用以下方法:
public interface IRandomizer
{
int Next(int inclusiveLower, int exclusiveOuter);
}
然后,我將公開一個帶有默認實現的靜態類,以及一個可選的工廠方法,以創建特定的“種子”實例。 請注意,內部使用的生成器( Default
)是公開可訪問的,但完全可以完全是內部使用的:
//Note, the following code is an outline of the general idea
public static class RandomGenerator
{
private readonly static Lazy<Randomizer> inner = new Lazy<Randomizer>();
public static IRandomizer Default { get { return inner.Value; } }
public static IRandomizer CreateNew(Random seed)
{
return new Randomizer(seed);
}
private class Randomizer : IRandomizer
{
private readonly Random random;
private readonly object syncLock = new object();
public Randomizer(Random seed = null)
{
random = seed ?? new Random();
}
public int Next(int minValue, int maxValue)
{
lock (syncLock)
{
return random.Next(minValue, maxValue);
}
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.