2013-04-15 45 views
8

我想實現下面的類:什麼是C++ 11隨機分佈?

typedef std::mt19937 Engine; 

class Interval 
{ 
public: 
    double upperBoundary; 
    double lowerBoundary; 
    double generateUniformRandomNumber(Engine& engine); 
}; 

我希望類的多線程環境中工作。每個線程都有自己的Engine對象實例,它會將Engine傳遞給具有隨機行爲的任何類的對象。

爲了均勻地產生隨機數的C++ 11的方式,在generateUniformRandomNumber的實施必須是這樣的:

uniform_real_distribution<double> distribution_; // private member of Interval 

double Interval::generateUniformRandomNumber(Engine& engine) 
{ 
    return distribution_(engine); 
} 

的問題是,我不知道C++ 11分佈。我知道C++ 11隨機數引擎可以是非常大的對象(幾千字節),但分佈情況如何?起初我以爲分佈只是簡單的函數,其中operator()pure const函數,但它似乎既不是pure也不是const。根據reference,每個分發實例都有一個reset()成員函數。這意味着它有一個很大的內部狀態或者一個緩存。

我的問題是:

  1. 難道分佈有一個內部狀態?如果是,爲什麼?標準是否會說明這個州的規模?

  2. 像我一樣做一個實現是一個好主意嗎?有沒有更好的辦法?

+3

作爲一個例子,我實現了一個[beta版本](https://gist.github.com/sftrabbit/5068941),其狀態實際上是兩個伽瑪分佈。 'reset'什麼也不做,因爲它只是要求任何下面的值獨立於以前的引擎使用。 –

+0

@sftrabbit那麼在你調用'operator()'的時候有人做了一個分配來積累狀態的'reset()'呢?例如,每個後續調用'operator()'都可以給你一個增加的範圍......這也解釋了爲什麼'operator()'不是const我猜? – David

+0

@Dave是的,當你繼續調用'operator()'的時候,沒有任何理由可以改變分佈。這只是意味着結果值依賴於以前的調用。 –

回答

2

放眼文檔爲RandomNumberDistribution template policy ...

reset()

復位分配對象的內部狀態。在調用 此函數後,分配對象 上運算符()的下一次調用將不依賴於之前對operator()的調用。

這意味着調用operator()可以改變狀態,影響後續調用operator()。這就是爲什麼reset()存在以及爲什麼operator()不是const

uniform_real_distribution應該是一個小的簡單仿函數,就像你說的。它可能只是持有它所構建的2 Real,沒有別的。而reset()應該不會爲此做任何事情。

6

分佈可能會非常好,通常會有一些狀態。該標準在這裏沒有給出任何限制。我可以想到幾種可能使用狀態的原因:

  1. 隨機數分佈通常有一些參數來配置它。例如,正態分佈具有均值和方差參數。這些是其國家的一部分,因爲它們必須在兩次調用之間進行。

  2. 的分佈在其他一些分配方面實現。你可以真正把它看作是一個更復雜的參數。例如,我的beta distribution實現保留兩個伽瑪分佈,每個分佈都有自己的配置。

  3. 的分佈可能會隨時間而改變。沒有什麼可以說分發的重複調用需要獨立。這就是reset成員函數的用武之地。大多數發行版都operator()獨立電話等等reset函數實際上什麼也不做(其定義爲空)。但是,如果您的呼叫是相關的,則reset應該使分配恢復到下一個呼叫獨立的狀態。

你的實現似乎罰款。一個uniform_real_distribution<double>是不太可能有更多的狀態,你構建它的參數。

2

是的,分佈可以有內部狀態。他們通常很小,但如果你關心的大小,檢查它。

2

的規範reset()狀態:

d的後續用途不依賴於通過之前調用復位任何發動機產生的值。

這意味着,通常的operator()調用可以取決於由在operator()之前調用使用發動機產生的值。也就是說,分配可以緩存或以其他方式取決於之前的引擎結果。

例如,伯努利分佈可能只需要一位來產生結果,而給定引擎一次提供32位,所以分佈可能會緩存32位,並且不會再次調用任何引擎,直到已經產生了32個值。

另一個例子是分佈(我忘了),其中所述公共算法自然地產生在時間的兩個值,所以分佈可能保存第二個值用於下一次呼叫。

所以,是的,分佈可以有內部狀態。該標準沒有要求這個州的規模。

如果你問如果它會好起來的線程之間共享分佈則沒有,這不是一個好主意。一方面這樣做是數據競爭,並導致未定義的行爲,除非您添加同步或使分配常量(即使您可以通過執行標準庫來實現這一點,但不是可移植的)。其次,該標準僅在您以特定方式使用分配和引擎並且在多個引擎之間共享分配不是方式時才作出保證。共享分配不太可能會產生錯誤的數據,但海事組織不應該這樣做。相反,你可能會讓每個線程保持自己的引擎和自己的分配。