C/C++でやっています。
C++11 で追加された std::random をクラス化して使いやすくしています。
( そのまま使う方法もありますが、乱数生成する方法だけでもかなりあって面倒なので。 )
C++
1#include<random> 2#include<cfloat> 3// それ以外のヘッダで使うやつもインクルード。 4 5class CRandom{ 6 public: 7 CRandom( double min = 0, double max = 0, size_t seed = time( nullptr ) ); 8 ~CRandom(); 9 10 double RandDouble( void ); 11 int RandInt( void ); 12 private: 13 std::mt19937 gen; 14 private: 15 double min; 16 double max; 17}; 18 19 20using namespace std; 21 22 23/************************************************************** 24* 25* クラス名: CRandom 26* 27* 種 類: コンストラクタ 28* 29* 目 的: 乱数を生成する 30* 31* 引 数: 32* double min := 最小値 ( デフォルト: 0 ) 33* double max := 最大値 ( デフォルト: 0 ) 34* size_t seed := シード値 ( デフォルト: time(nullptr) ) 35* 36* 参 ・ 引: 37* 38* 39* 備 考: 40* 41* 42**************************************************************/ 43 44CRandom::CRandom( double min, double max, size_t seed ){ 45 mt19937 temp( seed ); 46 47 // コピー 48 gen = temp; 49 50 this->min = min; 51 52 this->max = max; 53} 54 55 56 57/************************************************************** 58* 59* クラス名: CRandom 60* 61* 種 類: デストラクタ 62* 63* 目 的: 64* 65* 引 数: 66* 67* 68* 参 ・ 引: 69* 70* 71* 備 考: 72* 73* 74**************************************************************/ 75 76CRandom::~CRandom(){ 77 78} 79 80 81 82/************************************************************** 83* 84* クラス名: CRandom 85* 86* 関 数 名: RandDouble 87* 88* 目 的: double型の乱数発行 89* 90* 引 数: 91* void 92* 93* 戻 り 値: 94* 乱数 : double 95* 96* 使 用 例: 97* double d = CRandom.RandDouble(); 98* 99* 参 ・ 引: 100* 101* 102* 備 考: 103* 104* 105**************************************************************/ 106 107double CRandom::RandDouble( void ){ 108 109 if( DoubleCmp( min, max ) == 0 ){ 110 // ここが困っている部分。 111 112 /* 113 // 方法1: RandIntメンバ関数のときと同じ gen() で生成し、それをdoubleにキャスト 114 return (double)gen(); 115 */ 116 117 /* 118 // 方法2: 最大値と最小値を(別の)乱数で考える 119 double r = gen(); 120 this->min = (double)(r * (-1)); // -1 をかければ 負の数になる 121 this->max = (double)r; // 最大値はそのまま 122 */ 123 124 /* 125 // 方法3: (最小値と最大値の)決め打ち 126 this->min = 000000000000000000.222507; // 適当? 127 this->max = 1797000000000000; // 適当? 128 */ 129 130 /* 131 // 方法4: cfloat ヘッダにある doubleの有効範囲定数を使用する 132 this->min = DBL_MIN; 133 this->max = DBL_MAX; 134 */ 135 136 uniform_real_distribution<> dist( min, max ); 137 138 /* 139 // 方法5: uniform_real_distribution<> の引数無しでやってみる 140 uniform_real_distribution<> dist; 141 */ 142 143 return dist(gen); 144 }else{ 145 // 少数として生成する 146 uniform_real_distribution<> dist( min, max ); 147 return dist( gen ); 148 } 149} 150 151 152 153/************************************************************** 154* 155* クラス名: CRandom 156* 157* 関 数 名: RandInt 158* 159* 目 的: int型の乱数発行 160* 161* 引 数: 162* void 163* 164* 戻 り 値: 165* 乱数 : int 166* 167* 使 用 例: 168* int i = CRandom.RandInt(); 169* 170* 参 ・ 引: 171* 172* 173* 備 考: 174* 175* 176**************************************************************/ 177 178int CRandom::RandInt( void ){ 179 180 if( DoubleCmp( min, max ) == 0 ){ 181 return gen(); 182 }else{ 183 // 整数として生成する 184 uniform_int_distribution<> dist( (int)min, (int)max ); 185 return dist( gen ); 186 } 187}
のようにしています。
ソースコード上には、DoubleCmp(...) というのがありますが、
これは別のファイルで double型データを比較する関数だとします。
strcmp関数みたいに 同じであれば 0 を返します。
つまり、上記コードの if( DoubleCmp( ... ) == 0 ) の部分は、
「引数として与えられたmin, max が 同じであるとき」という意味です。
一応機能するのですが、
問題は (0,0) や (1,1) のように min = max の状態 であるときの RandDoubleメンバ関数 が返す値です。
main関数でためしに
C++
1CRandom Random; // デフォルト引数を使用。 2 3for( int i = 0; i < 10; i++ ){ 4 cout << Random.RandDouble() << endl; 5}
とやってみると、
1.12043e+015 1.63118e+009 -7.702e+008 -2.74263e+009 9.6332e+008 2.72246e+009 2.6308e+009 -1.82902e+009 2.18942e+009 1.27056e+009
のようになります。
表示データを見ると、
1.12043e+015 という風に、科学的記数法というのでしょうか?
これになってしまいます。
ちゃんとした引数を与えて ( ただし min != maxであること。例えば、(0.53, 100.35) 等。 ) やってみると、
82.3097 68.0833 90.1891 24.8984 53.918 97.9953 71.7978 60.8671 47.8723 28.3752
という風になります。
私がやりたいのは、1.63118e+009 みたいな乱数データ取得ではなく、82.3097 のような 乱数データ取得です。
これって不可能なのでしょうか?
一応思いついた 方法1~方法5まではすべて試してみました。
しかし、同じでした。 ( もちろん、乱数なので "完全に同じ" ではないですが。 )
何か方法があるのでしょうか?
[情報]
言語 : C/C++ ( C++11 )
コンパイラ: MinGW ( VC++特有の関数とか使えない... )
宜しくお願い致します。
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2017/07/01 04:09
2017/07/01 05:19
2017/07/01 05:50