5

これら 2 つのコード ブロックが異なる出力を与える理由がわかりません。

unsigned int seed1 = 0;
char state1[256];
initstate(seed1, state1, 256);
printf("%10ld\n", random());
printf("%10ld\n", random());
// Gives:
// 1216130483
// 1950449197

対。

unsigned int seed1 = 0;
char state1[256];
initstate(seed1, state1, 256);
printf("%10ld\n", random());
setstate(state1);
printf("%10ld\n", random());
// Gives:
// 1216130483
// 625602885

setstate() の機能を誤解していますか?

編集:興味深いことに、これが与えるものを見てください:

unsigned int seed1 = 0;
char state1[256];
initstate(seed1, state1, 256);
printf("%10ld\n", random());
setstate(state1);
setstate(state1);
printf("%10ld\n", random());
// Gives:
// 1216130483
// 1950449197
4

4 に答える 4

3

どちらの実装も正しいです。

Setstate は、ルーチン内の静的ポインターをバッファーを指すように変更するだけです。

initstate は同じことを行うことができますが、バッファの内容を最初に変更することもできます。PRNG が ARC4 や Spritz のようなものである場合、バッファーは単なる任意のビットではなく順列である必要があります。PRNG が非線形加法フィードバック ジェネレーターである場合、状態のどこかにある下位ビットの少なくとも 1 つを設定する必要があります。そうしないと、正しく機能しません。また、一部のライブラリは状態バッファーをハッシュするため、シードと出力の情報だけではどのような PRNG が使用されているかを簡単に判断できません。必須ではありません。lib が使用しているジェネレーターが LFSG であるか、特定のフォーマットを必要としないか、バッファーに一貫性を必要としないものである場合、lib は initstate と setstate に対してまったく同じことを行うことができます。しかし、initstate を実行せず、OS がそのようなニーズを持つものを使用している場合、

于 2016-08-11T20:41:10.610 に答える
2

initstate()への呼び出しもその状態に切り替わることはないと思いますが、への呼び出しは切り替わるsetstate()ため、後者のrandom()呼び出しは新しい状態から生成された数値を返します。

于 2012-12-06T10:18:12.607 に答える
2

の BSD 実装はsetstate、古いバッファに格納する前に、エラー チェックの目的で補助状態情報をロードします。さらにinitstatesetstateこの情報を更新する関数は と だけです。これは、同じバッファが使用される場合、古い状態をロードし新しいデータを格納し、内部状態を前者で更新することを意味します。この方法で繰り返し呼び出すsetstateと、古い保存状態と現在の内部状態が交互に切り替わり、2 回呼び出されたときに観察される結果が生じます。

のコメントにsetstateは、現在のバッファで呼び出しても問題ないことが示されているため、これは意図された動作であるか、何十年も前のバグです。

処理の順序により、現在の状態と同じ状態で setstate() を呼び出しても問題ないことに注意してください。

于 2016-08-11T22:50:16.560 に答える