Delphiのランダム機能はどれほど信頼できますか
-
08-10-2019 - |
質問
Delphiで統計テストを書くプログラム(Delphiである必要があります)を書いていますが、ランダム機能はやや奇妙であると聞きました。プログラムが開始されたときにランダム関数のシードをランダム化するには、ランダム化を呼び出す必要があります。
ランダム関数(ランダム化を呼び出した後)が統計テストに十分なランダムであるのか、それともMersenne Twisterが必要かどうか疑問に思っていますか?これがどれほど重要かを教えてくれるランダムの実際の実装についての洞察はありますか?
解決
どうにか Random
統計テストは、使用する意図のコンテキストに依存します。
そうは言っても、私は適切な統計を行う必要があるデルファイコードのいくつかを書き、使用しました Random
たとえば、さまざまなヌル分布、データの擬似複製、および再サンプリングを取得するため。これまでのところ、私は自分のコードでケースに出会っていません Random
偏ったまたは信頼性の低い結果、または意図した統計テストの使用を妨げていた結果をもたらすでしょう。しかし、私のコードのために保持されるものは、必ずしもあなたのために保持する必要はありません。
疑わしい場合は、もちろん呼び出しの結果を統計的に分析できます Random
(例:R、SPSなど)。結果の分布が特定の統計テストの分布要件に違反するかどうかを調べます。 [あなたが適切な科学者なら、これはとにかくあなたがすべきことです。
他のPRNGが必要な場合 - 例: tpmath ライブラリにはいくつかが含まれています。 (より複雑なことについては、Delphi経由でRから精巧な統計関数を呼び出すオプションもあります。)
他のヒント
DelphiのPRNGは、ほとんどすべてのプログラミング言語RTL PRNGと同様に、 線形合同ジェネレーター.
ほとんどの小規模なものには十分ですが、注意すべきことがあります。特に、低次のビットに注意してください。乗算のパターンと追加は、低次のビットがまったくランダムではないことを意味します。しかし、これは通常、引き出されてから切り捨てられた大きな32ビット値にのみ適用されます mod
または類似。使用 Random(10)
0から9の間の値を内部的に使用して、32ビット範囲全体で乗算を使用します。 mod
手術。
抵抗できませんでした。
乱数の独自性を最も速い実行時間で保証する方法を求めている場合、 about.com 挑戦を生み出しました 最速の一意の乱数ジェネレーター, 、 と Patrick Van Logchemの実装 勝者として選出されました。
比較的難解なハードウェアを購入しない限り、コンピューターが提供できる乱数の最良の近似は、完全に決定論的な擬似ランダムシーケンスです。一般に、ランダム化関数は、比較的ランダムな値(多くの場合、時間に基づいていますが、マウスの動きに基づいていることがあります - デルフィが何をしているのかわかりません)を使用します。これがなければ、あなたは毎回同じ順序で同じ乱数セットを取り戻すことになります。これは、そもそも乱数を使用する目的を打ち負かす傾向があります。
さて、これは信頼性についての質問に答えていないことを理解していますが、ランダム化を呼び出すことを要求することは、悪い発電機ではなく良い発電機の兆候であるという自信を与えるはずです。数値のシーケンスがランダムなものであることを示す統計テストがたくさんあり、Delphi乱数ジェネレーターは成熟した製品であるため、多くの目的に適している可能性があります。
可能性のプールに追加するために - Windowsはさまざまな内蔵を提供します 暗号化機能. 。デフォルトではまだ含まれていない場合は、おそらくデルファイラッパーもあります。
これらの機能の中には、aもあります 暗号化的に強い乱数ジェネレーター. 。これは、非常に長い要因リストに基づいてシードするため、ソフトウェアで得られる最高のランダム性です。確かではありませんが、ハードウェアランダム数ジェネレーターがある場合は、ハードウェアランダム数ジェネレーターも使用すると思います。
それだけでは不十分な場合は、でサインアップすることもできます 量子ランダムビットジェネレーターサービス いくつかのための 本当 ランダム値。
EmbarcaderoのWebサイトから:
_lrandは、長い乱数ジェネレーター関数です。 _Randは、期間2^64の乗算的合同乱数ジェネレーターを使用して、0から2^31-1の範囲の連続した擬似ランダム数を返します。
ジェネレーターは、1の引数値でSRANDを呼び出すことにより再初期化されます。特定のシード番号でSRANDを呼び出すことにより、新しい出発点に設定できます。
私が分析して以来、実装を変更しなかった場合(Delphi 4 IIRC)、Delphi PRNGは次のように実装されています。
Randseed:=int32(Randseed*$08088405)+1
result:=Randseed*Range shr 32
(擬似コード/乗算が任意に大きな整数にあると仮定)
0..9の間にランダムを返します
StrToInt(copy(FloatToStr(Random),4,1))
注:使用前にfloattostostr(ランダム)長さを確認するか、小数部から他の数字を使用してください...