/** * @file test2.cpp * @brief C言語によるアルゴリズム辞典、のrndtest.c による測定 * @author tenk* * @date 2010-1 */ #define XORSHIFTRAND_TEST #include <stdio.h> #include <stdlib.h> #include <math.h> #include "XorShiftRand.h" #include "MtRand.h" // =========================================================================== /// 適当な線形合同法の乱数. (http://www001.upp.so-net.ne.jp/isaku/rand.html の rand( )その1) class Test_Rand1 { unsigned s_; public: Test_Rand1() : s_(1) {} double operator()() { return (s_ = s_ * 1103515245+12345) / (0xFFFFFFFF + 1.0); } }; /// C標準ライブラリの rand() を呼び出す. struct Test_Clib_Rand { double operator()() { return rand() / (RAND_MAX+1.0) ; } }; template<class R> struct Test_Rnd : public R { double operator()() { return R::get() / (0xFFFFFFFF + 1.0); } }; // =========================================================================== // 計測&チェック template<class RND> void test(RND rnd, size_t count, unsigned flags, const char* ttl, double& r1, double& r2) { unsigned char verboss = flags & 1; if (verboss) { fprintf(stderr, "\t%s:start\n", ttl); } double x0 = rnd() - 0.5; double xprev = x0; double s1 = x0; double s2 = x0 * x0; double r = 0; double x = 0; unsigned n = count; for (unsigned i = 1; i < n; ++i) { x = rnd() - 0.5; s1 += x; s2 += x * x; r += xprev * x; xprev = x; } r = (n * (r + x * x0) - s1 * s1) /(n * s2 - s1 * s1); r1 = s1 * sqrt( 12.0 / n ); r2 = ((n-1) * r + 1) * sqrt((n + 1.0) / (n * (n - 3.0))); return; } static void test_all(unsigned count, unsigned flags) { enum { N = 64 }; const char* nm[N] = {0}; double r1[N] = {0}, r2[N] = {0}; printf("C言語によるアルゴリズム辞典、のrndtest.c による測定\n", count); printf(" -0.5〜0.5の乱数を %9d 回実行\n", count); // いくつかのテスト呼び出し. { unsigned k = 0; nm[k] = "XorShift 32" ; test(Test_Rnd<XorShiftRand<32> >() , count, flags, nm[k], r1[k], r2[k]); ++k; nm[k] = "XorShift 64" ; test(Test_Rnd<XorShiftRand<64> >() , count, flags, nm[k], r1[k], r2[k]); ++k; nm[k] = "XorShift 96" ; test(Test_Rnd<XorShiftRand<96> >() , count, flags, nm[k], r1[k], r2[k]); ++k; nm[k] = "XorShift 128" ; test(Test_Rnd<XorShiftRand<128> >(), count, flags, nm[k], r1[k], r2[k]); ++k; nm[k] = "XorShift 160" ; test(Test_Rnd<XorShiftRand<160> >(), count, flags, nm[k], r1[k], r2[k]); ++k; nm[k] = "XorShift 192" ; test(Test_Rnd<XorShiftRand<192> >(), count, flags, nm[k], r1[k], r2[k]); ++k; nm[k] = "XorShift 256" ; test(Test_Rnd<XorShiftRand<256> >(), count, flags, nm[k], r1[k], r2[k]); ++k; nm[k] = "LCG " ; test(Test_Rand1() , count, flags, nm[k], r1[k], r2[k]); ++k; nm[k] = "clib rand " ; test(Test_Clib_Rand() , count, flags, nm[k], r1[k], r2[k]); ++k; nm[k] = "MT Rand " ; test(Test_Rnd<MtRand>() , count, flags, nm[k], r1[k], r2[k]); ++k; } printf(" 以下は期待値との差を標準誤差で割ったもの.\n"); printf(" 20回中19回は ±2以内に入るはず.\n"); printf("[1] 平均値 \n"); printf("[2] 隣どうしの相関係数: \n"); printf(",%-21s ,%6s,%6s\n", "方法", "[1]", "[2]"); for (unsigned j = 0; j < N; ++j) { if (nm[j] == 0) continue; printf(",%-21s ,%6.3f,%6.3f\n", nm[j], r1[j], r2[j]); } } // =========================================================================== /** 使い方. */ static int usage() { fprintf(stderr, "usage>test [-opts] file(s)\n" " xor shift 乱数チェック.\n" " -cN 試行回数の指定\n" " -v 経過メッセージを増やす\n" ); return 1; } /** メイン. */ int main(int argc, const char* argv[]) { int i; unsigned count = 1; unsigned flags = 0; if (argc < 2) return usage(); // オプション取得. for (i = 1; i < argc; ++i) { const char* a = argv[i]; if (a[0] == '-') { if (a[1] == 'v') { flags = 1; // verboss; } else if (a[1] == 'c') { count = strtol(a+2,0,0); if (count < 1) count = 1; } else { return usage(); } } } test_all(count, flags); return 0; }