Created
October 16, 2015 18:32
-
-
Save hirosof/fd77ff2f86ac1049495d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
乱数精度テスト | |
*/ | |
// インクルード部 | |
#include <iostream> | |
#include <cstdio> | |
#include <random> | |
#include <cstdlib> | |
#include <ctime> | |
#include "CHSRandom.hpp" //乱数アルゴリズムxorshiftを用いた自作乱数クラス | |
using namespace std; | |
//定数定義部 | |
#define COUNT_ARRAY_NUMS 16 | |
#define MAX_NUMBER_OF_TESTS 268435456 | |
#define MIN_NUMBER_OF_TESTS COUNT_ARRAY_NUMS | |
//プロトタイプ宣言 | |
void InitRandomSystem ( void ); | |
//乱数値取得用 | |
unsigned int GetRandom ( int algoId ); | |
//乱数テスト関数 | |
void RandomTest ( int algoId); | |
//グローバル変数 | |
unsigned int seed; //シードの退避 | |
unsigned int testNums; //テスト数 | |
unsigned int incrementnum; //インクリメント用 | |
//アルゴリズム名 | |
static const char AlgoName [ 9 ] [ 27 ] = { | |
"C言語標準rand関数" , "xorshift" , "線形合同法" , | |
"メルセンヌ・ツイスター" , "ディスカードブロック法" , "キャリー付き減算法" , | |
"シャッフルオーダー法" , "環境依存な真の乱数生成器" , "インクリメント式" | |
}; | |
int MaxAccurateAlgoID = 0; | |
double MaxAccuratePercent = 0; | |
double AccuratePercent [ 9 ]; | |
//グローバル宣言(乱数系) | |
CHSRandom xorshift; //xorshift | |
//C++ STL 乱数 クラス | |
minstd_rand minstd; //線形合同法 | |
mt19937 mtrand; //メルセンヌ・ツイスター | |
ranlux24 ralux; //ディスカードブロック法 | |
ranlux24_base raluxbase; //キャリー付き減算法 | |
knuth_b knuth; //シャッフルオーダー法 | |
random_device randdev; //環境依存な真の乱数生成器 | |
int main ( void ) { | |
//乱数初期化 | |
InitRandomSystem (); | |
printf ( "1アルゴリズム当たりのテスト回数を指定してください:" ); | |
scanf ( "%u" , &testNums ); | |
if ( testNums < MIN_NUMBER_OF_TESTS ) { | |
testNums = MIN_NUMBER_OF_TESTS; | |
printf ( "入力された数が小さすぎるため%d回にしました。\n" , testNums ); | |
} else if ( testNums > MAX_NUMBER_OF_TESTS ) { | |
testNums = MAX_NUMBER_OF_TESTS; | |
printf ( "入力された数が大きすぎるため%d回にしました。\n" , testNums ); | |
} | |
//全テストを行う | |
for ( int i = 0; i < 9; i++ ) { | |
RandomTest ( i ); | |
} | |
//テスト結果表示 | |
printf ( "\n<<テスト結果>>\n" ); | |
printf ( "%26s ・・・ 精度率\n" ,"アルゴリズム名"); | |
for ( int i = 0; i < 9; i++ ) { | |
printf ( "%26s ・・・ %7.4f%%\n" , AlgoName [ i ] , AccuratePercent [ i ] ); | |
} | |
printf ( "\n最も高性能なアルゴリズムは[%s]で精度率は[%7.4f%%]です。\n" , AlgoName [ MaxAccurateAlgoID ] , MaxAccuratePercent ); | |
return 0; | |
} | |
void InitRandomSystem ( void ){ | |
//シードは現在時刻 | |
seed = (unsigned) time ( NULL ); | |
//seed = 1; | |
//C標準ライブラリ | |
srand ( seed ); | |
//xorshift | |
xorshift.SetSeed ( seed ); | |
//線形合同法 | |
minstd.seed(seed); | |
//メルセンヌ・ツイスター | |
mtrand.seed(seed); | |
//ディスカードブロック法 | |
ralux.seed ( seed ); | |
//キャリー付き減算法 | |
raluxbase.seed ( seed ); | |
//シャッフルオーダー法 | |
knuth.seed ( seed ); | |
//インクリメント用 | |
incrementnum = seed; | |
} | |
unsigned int GetRandom ( int algoId ) { | |
switch ( algoId) { | |
case 0: | |
//C言語標準ライブラリ | |
return rand (); | |
case 1: | |
//xorshift | |
return xorshift (); | |
case 2: | |
//線形合同法 | |
return minstd (); | |
case 3: | |
//メルセンヌ・ツイスター | |
return mtrand (); | |
case 4: | |
//ディスカードブロック法 | |
return ralux(); | |
case 5: | |
//キャリー付き減算法 | |
return raluxbase (); | |
case 6: | |
//シャッフルオーダー法 | |
return knuth (); | |
case 7: | |
return randdev (); | |
case 8: | |
{ | |
unsigned int ret = incrementnum; | |
incrementnum++; | |
return ret; | |
} | |
default: | |
return 0; | |
} | |
} | |
void RandomTest ( int algoId ) { | |
unsigned int CountVals [ COUNT_ARRAY_NUMS ]; //カウント用バッファ | |
unsigned int AverageCount; | |
//平均な標準回数 | |
AverageCount = testNums / COUNT_ARRAY_NUMS; | |
//バッファ初期化 | |
for ( int i = 0; i < COUNT_ARRAY_NUMS; i++ ) CountVals [ i ] = 0; | |
printf ( "\n<<[%s]による乱数精度チェック>>\n" , AlgoName [ algoId ] ); | |
int nowp , oldp = -1; | |
unsigned int rnum; | |
for (unsigned int i = 0; i < testNums; i++ ) { | |
rnum = GetRandom ( algoId ) % COUNT_ARRAY_NUMS; | |
CountVals [ rnum ]++; | |
nowp = (int) ( ( i + 1 ) * 100.0 / testNums ); | |
if ( nowp != oldp ) { | |
printf ( "\r%4d%% 完了 (%10d / %10d)" , nowp , i + 1 , testNums ); | |
oldp = nowp; | |
} | |
} | |
printf ( "\n\n出現分布表\n" ); | |
int dist = 0; | |
for ( int i = 0; i < COUNT_ARRAY_NUMS; i++ ) { | |
printf ( "%6d ・・・ %10d回 [%7.4f%%]\n" , i , CountVals [ i ] , CountVals [ i ] * 100.0 / testNums ); | |
dist += ( AverageCount > CountVals [ i ] ) ? AverageCount - CountVals [ i ] : CountVals [ i ] - AverageCount; | |
} | |
double AP = 100.0 - (dist * 100.0 / testNums); | |
printf ( "\n%6s ・・・ %10d回[%7.4f%%]\n" , "誤差率" , dist , 100 - AP ); | |
printf ( "%6s ・・・ %10d回[%7.4f%%]\n" , "精度率" , testNums - dist , AP ); | |
if ( AP > MaxAccuratePercent ) { | |
MaxAccuratePercent = AP; | |
MaxAccurateAlgoID = algoId; | |
} | |
AccuratePercent[algoId] = AP; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment