システムのテストとデバッグのために、Cでいくつかの乱数を生成する必要があります。このシステムは、機能のセットが限られているカスタムハードウェア(SoC)であるため、基本的な数学演算しか使用できません。
いいえ、stdlibまたはmath.hで乱数ジェネレーターを使用することはできません。自分で書く必要があります。では、乱数を生成するためのある種のアルゴリズムはありますか?
簡単な解決策は、ここでワークステーションに数値を生成してモジュールに埋め込むことですが、それはしたくありません。
システムのテストとデバッグのために、Cでいくつかの乱数を生成する必要があります。このシステムは、機能のセットが限られているカスタムハードウェア(SoC)であるため、基本的な数学演算しか使用できません。
いいえ、stdlibまたはmath.hで乱数ジェネレーターを使用することはできません。自分で書く必要があります。では、乱数を生成するためのある種のアルゴリズムはありますか?
簡単な解決策は、ここでワークステーションに数値を生成してモジュールに埋め込むことですが、それはしたくありません。
CACMの88年10月号のParkandMillerによる記事を掘り下げてください。
彼らが提案する一般的なアルゴリズムは次のとおりです。
a = 16807;
m = 2147483647;
seed = (a * seed) mod m;
random = seed / m;
記事にはいくつかの改良が含まれていますが。
乱数ジェネレーターは基本的に、開始シードから再帰的に実行される特別な*ハッシュ関数です。
C#コードでMurmurHash2アルゴリズムを使用して効果を上げました。実装は非常に高速で簡単であり、低い衝突率で非常によく分散されることがテストされています。プロジェクトには、Cに簡単に変換できるC++で記述されたいくつかの異なるオープンソースハッシュ関数があります。
*特別な意味で、ある値に対してハッシュ関数を実行すると、一見ランダムな(ただし確定的な)別の値が返され、出力がパターンを形成していないように見えます。また、戻り値の分布は一様分布である必要があります。
gslライブラリのソースコードを確認してください。十分にテストされたアルゴリズムがいくつか実装されています。
ジョージ・マルサグリアのキャリー付き倍算を試すことができます。
ウィキペディアのコード:
#include <stdint.h>
#define PHI 0x9e3779b9
static uint32_t Q[4096], c = 362436;
void init_rand(uint32_t x)
{
int i;
Q[0] = x;
Q[1] = x + PHI;
Q[2] = x + PHI + PHI;
for (i = 3; i < 4096; i++)
Q[i] = Q[i - 3] ^ Q[i - 2] ^ PHI ^ i;
}
uint32_t rand_cmwc(void)
{
uint64_t t, a = 18782LL;
static uint32_t i = 4095;
uint32_t x, r = 0xfffffffe;
i = (i + 1) & 4095;
t = a * Q[i] + c;
c = (t >> 32);
x = t + c;
if (x < c) {
x++;
c++;
}
return (Q[i] = r - x);
}
メルセンヌツイスターを探すことをお勧めします。より高品質のアルゴリズムがたくさんあります。ここで見つけた概要を含む良い記事: