2017-02-21 81 views
2

以前已詢問過此問題(stackoverflow),但(接受的)答案不令人滿意。在C++中保存並加載隨機數生成器狀態11

下面的示例保存並加載狀態,但取決於生成值的數量它工作,或者沒有:

#include <fstream> 
#include <iostream> 
#include <random> 
#include <cassert> 

int main() 
{ 
    const int preN = 4; 
    const int middleN = 0; 

    // initialize randGen 
    std::mt19937 randGen1; 
    std::normal_distribution<double> distribution1; 


    // print some initial random numbers 
    for (int i=0;i<preN;++i) 
    std::cout << distribution1(randGen1)<<" "; 

    // save state 
    std::cout << std::endl << "Saving...\n"; 
    { 
    std::ofstream fout("seed.dat"); 
    fout << randGen1; 
    } 

    // maybe advance randGen1 
    for (int i=0;i<middleN;++i) 
    std::cout << distribution1(randGen1)<<" "; 

    // load saved state into randGen2 
    std::cout << std::endl << "Loading...\n"; 
    std::ifstream fin("seed.dat"); 
    std::mt19937 randGen2; 
    fin >> randGen2; 
    std::normal_distribution<double> distribution2; 

    // are both randGen equal? 
    assert(randGen1 == randGen2); 

    // print numbers from both generators 
    std::cout << "Generator1\tGenerator2\n"; 
    std::cout << distribution1(randGen1) << "\t" 
      << distribution2(randGen2) << "\n"; 

    return 0; 

}  

有了這些參數,就像預期。但是,如果我設置preN=3輸出的樣子:

0.13453 -0.146382 0.46065 
Saving... 

Loading... 
Generator1 Generator2 
-1.87138 0.163712 

爲什麼斷言不適用?現在我設置preN=3middleN=1和輸出

0.13453 -0.146382 0.46065 
Saving... 
-1.87138 
Loading... 
Generator1 Generator2 
0.163712 0.163712 

如果我設置middleN到任何比1斷言適用於較大。 任何人都可以解釋發生了什麼?我在做什麼錯誤或不理解?

與GCC5.4.0和CLANG3.8.0在Linux上

回答

4

測試的問題是不是你的隨機數生成器的狀態。問題是您的分配的狀態。是的,分佈也可以有狀態。

您可以通過使用reset重置正態分佈的狀態來獲得相同的值。或者,您也可以使用<<>>這個分配的狀態preserve and reconstitute

+0

試了一下太(因爲這種行爲看上去迷人,我沒有嘗試C++很長一段時間),可以說爲當然,一個統一的dist的行爲不同! – sascha

+0

@sascha:我不確定你的意思是表現不同。 –

+0

它可能沒有一個重要的內部狀態(比普通的dist更簡單),但這只是經驗觀察。這只是我的第一次試用。也許它也是。忽略我的評論。很好的答案! – sascha

1

由於從上面Nicol Bolas答案,我可以在下方添加糾正代碼:

#include <fstream> 
#include <iostream> 
#include <random> 
#include <cassert> 

int main() 
{ 
    const int preN = 7; 
    const int middleN = 0; 

    // initialize another randGen 
    std::mt19937 randGen1; 
    std::normal_distribution<double> distribution1; 

    // print some initial random numbers 
    for (int i=0;i<preN;++i) 
    std::cout << distribution1(randGen1)<<" "; 

    // save state 
    std::cout << std::endl << "Saving...\n"; 
    { 
    std::ofstream fout("seed.dat"); 
    fout << randGen1; 
    fout.close(); 
    std::ofstream fout2("distribution.dat"); 
    fout2 << distribution1; 
    fout2.close(); 
    } 

    // maybe advance randGen 
    for (int i=0;i<middleN;++i) 
    std::cout << distribution1(randGen1)<<" "; 

    // load saved state into randGen2 
    std::cout << std::endl << "Loading...\n"; 
    std::mt19937 randGen2; 
    std::normal_distribution<double> distribution2; 
    { 
    std::ifstream fin("seed.dat"); 
    fin >> randGen2; 
    fin.close(); 
    std::ifstream fin2("distribution.dat"); 
    fin2 >> distribution2; 
    fin2.close(); 
    } 

    // are both randGen equal? 
    assert(randGen1 == randGen2); 
    assert(distribution1 == distribution2); 

    // print numbers from both generators 
    std::cout << "Generator1\tGenerator2\n"; 
    std::cout << distribution1(randGen1) << "\t" 
      << distribution2(randGen2) << "\n"; 

    return 0; 
}