Skip to content

Instantly share code, notes, and snippets.

@hirosof
Created October 16, 2015 18:32
Show Gist options
  • Save hirosof/fd77ff2f86ac1049495d to your computer and use it in GitHub Desktop.
Save hirosof/fd77ff2f86ac1049495d to your computer and use it in GitHub Desktop.
/*
乱数精度テスト
*/
// インクルード部
#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