Cでいくつかの埋め込みコードを書いているので、Rand()関数を使用する必要があります。残念ながら、Rand()はコントローラーのライブラリではサポートされていません。高速であるが、さらに重要なことに、比較的高品質の乱数を生成するスペースのオーバーヘッドがほとんどない単純な実装が必要です。使用するアルゴリズムやサンプルコードを知っている人はいますか?
編集:それは画像処理用なので、「比較的高品質」とは、適切なサイクル長と優れた均一性を意味します。
これをチェックしてください 乱数ジェネレーターのコレクション ジョージマルサグリアから。彼は乱数生成の第一人者なので、彼が推奨するものなら何でも使用できると確信しています。そのリストのジェネレーターは小さく、状態として署名されていないlongを2つだけ必要とするものもあります。
マルサリアの発電機は、長期間の基準と良好な均一分布により、間違いなく「高品質」です。暗号化には合格しませんが、厳格な統計的検定に合格します。
Cコード for L'écuyerのLFSR11 を使用します。
unsigned int lfsr113_Bits (void)
{
static unsigned int z1 = 12345, z2 = 12345, z3 = 12345, z4 = 12345;
unsigned int b;
b = ((z1 << 6) ^ z1) >> 13;
z1 = ((z1 & 4294967294U) << 18) ^ b;
b = ((z2 << 2) ^ z2) >> 27;
z2 = ((z2 & 4294967288U) << 2) ^ b;
b = ((z3 << 13) ^ z3) >> 21;
z3 = ((z3 & 4294967280U) << 7) ^ b;
b = ((z4 << 3) ^ z4) >> 12;
z4 = ((z4 & 4294967168U) << 13) ^ b;
return (z1 ^ z2 ^ z3 ^ z4);
}
非常に高品質で高速です。 Rand()は何にも使用しないでください。役に立たないより悪いです。
これがANSICへのリンクです いくつかの乱数ジェネレーターの実装 。
コンパクトで組み込みシステムに適した乱数ジェネレーター " simplerandom "のコレクションを作成しました。コレクションは [〜#〜] c [〜#〜] および Python で利用できます。
私は見つけたシンプルでまともなものをたくさん探して、それらを小さなパッケージにまとめました。それらには、いくつかのマルサリアジェネレーター(KISS、MWC、SHR3)、およびいくつかのL'EcuyerLFSRジェネレーターが含まれます。
すべてのジェネレーターは符号なし32ビット整数を返し、通常は1〜4個の32ビット符号なし整数で構成される状態になります。
興味深いことに、Marsagliaジェネレーターにいくつかの問題が見つかり、それらすべての問題を修正/改善しようとしました。それらの問題は次のとおりです。
シードに関するいくつかの問題を発見し、堅牢なシード(初期化)手順を作成しようとしたので、「悪い」シード値を指定しても問題は発生しません。
ウィキペディアから少し:
Diehardテストを含む、統計的ランダムネスの多数のテストに合格します。これは、すべてではありませんが、さらに厳しいTestU01クラッシュランダム性テストのほとんどに合格します。
リンクで利用可能な多くの言語のソースコード。
学術論文をお勧めします 最小標準乱数ジェネレーターの2つの高速実装 DavidCartaによる。 Googleから無料のPDFを見つけることができます。MinimalStandardRandomNumberGeneratorに関する元の論文も読む価値があります。
Cartaのコードは、32ビットマシンで高速で高品質の乱数を提供します。より徹底的な評価については、論文を参照してください。
GNU Cライブラリから1つを取得します。ソースは、オンラインで閲覧できます。
http://qa.coreboot.org/docs/libpayload/Rand_8c-source.html
ただし、乱数の品質についてまったく懸念がある場合は、より注意深く記述された数学ライブラリを検討する必要があります。これは大きなテーマであり、標準のRand
実装は専門家によってあまり考えられていません。
別の可能性があります: http://www.boost.org/doc/libs/1_39_0/libs/random/index.html
(選択肢が多すぎる場合は、いつでもランダムに1つ選ぶことができます。)
私はこれを見つけました: Simple Random Number Generation、by John D.Cook 。
コードが数行しかないことを考えると、Cに簡単に適応できるはずです。
編集:そしてあなたは「比較的高品質」が何を意味するのかを明確にすることができます。核発射コードの暗号化キー、またはポーカーゲームの乱数を生成していますか?
さらに良いことに、複数の線形フィードバックシフトレジスタを使用して、それらを組み合わせます。
sizeof(unsigned) == 4
と仮定すると:
unsigned t1 = 0, t2 = 0;
unsigned random()
{
unsigned b;
b = t1 ^ (t1 >> 2) ^ (t1 >> 6) ^ (t1 >> 7);
t1 = (t1 >> 1) | (~b << 31);
b = (t2 << 1) ^ (t2 << 2) ^ (t1 << 3) ^ (t2 << 4);
t2 = (t2 << 1) | (~b >> 31);
return t1 ^ t2;
}
標準的な解決策は、 線形フィードバックシフトレジスタ を使用することです。
[〜#〜] kiss [〜#〜] という名前の単純なRNGが1つあり、3つの数値に応じた1つの乱数ジェネレーターです。
/* Implementation of a 32-bit KISS generator which uses no multiply instructions */
static unsigned int x=123456789,y=234567891,z=345678912,w=456789123,c=0;
unsigned int JKISS32() {
int t;
y ^= (y<<5); y ^= (y>>7); y ^= (y<<22);
t = z+w+c; z = w; c = t < 0; w = t&2147483647;
x += 1411392427;
return x + y + w;
}
また、RNGをテストするためのWebサイトが1つあります http://www.phy.duke.edu/~rgb/General/dieharder.php