我需要一種方法來獲得確定的整數和雙精度序列。
template <class U>
constexpr auto get_random_value (std::mt19937 &gen, U min_value, U max_value)->U
{
if constexpr ( std::is_same_v <U, double> or std::is_same_v <U, float> ){
std::uniform_real_distribution <U> distrib( min_value, max_value );
return distrib( gen );
}
else if constexpr ( std::is_same_v <U, u32> or std::is_same_v <U, i32> ){
std::uniform_int_distribution distrib( min_value, max_value );
return distrib( gen );
}
else {
throw std::runtime_error( "error value type" );
}
}
我的問題是日復一日,相同的種子值會導致不同的結果。分布是罪魁禍首,因為它在很大程度上避免了模數的陷阱。
但是我需要一種精確的方法來始終確定從給定種子開始的序列總是相同的。而且我需要一個無偏的磁區(所以 % 和 rand() 出來了)。
什么樣的實施可以保證這一點?
uj5u.com熱心網友回復:
C 標準中的發行版是不可移植的(“種子穩定”),因為結果可能會在不同的實作之間發生變化(例如 Microsoft STL 與 gcc libstdc 與 clang libc )甚至不同的版本(例如Microsoft 之前更改了他們的實作) )。該標準根本沒有規定特定的演算法,目的是允許實作為每個平臺選擇具有最佳性能的演算法。到目前為止,只有一個提案 (D2059R0)可以解決這個問題。但是請注意,生成器實際上是便攜式的。
我還沒有看到一個保證可移植性的庫。然而,在實踐中,眾所周知boost.random可以跨平臺產生可重現的結果(參見例如此處或此處或此處)。此外,谷歌的abseil庫明確宣告它們不提供穩定性保證,但似乎在不同平臺上產生相同的結果。這是Godbolt上的一個實時示例,您可以在某種程度上看到這一點(好吧,至少 Linux 與 Windows 的引數選擇很少)。重點是不要在不檢查重大更改的情況下更新庫。也比較例如這個博客文章。或者您也可以自己實作特定演算法(參見例如此處)或簡單地將代碼從一個庫復制到您的代碼庫,從而有效地凍結其版本。
對于涉及浮點運算的分布,您還有一個問題,一般來說,算術本身在跨平臺上遠非穩定,因為諸如自動矢量化(SSE2 與 AVX 等)或 FPU 設定之類的東西可能會改變行為。有關更多資訊,請參閱此博客文章。不幸的是,我不知道包括上述庫在內的發行版會受到多遠的影響。上面提到的關于 Godbolt 的小例子至少沒有顯示出任何問題-ffast-math,這是一個好兆頭。
無論您做什么,我強烈建議您通過適當的自動測驗(單元測驗等)來支持您的選擇,以捕捉任何潛在的行為偏差。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/513850.html
標籤:C 随机的分配
