it-swarm-ja.tech

乱数ジェネレーターはどのように機能しますか?

乱数ジェネレーターはどのように機能しますか? (たとえば、C/C++ Java)

独自の乱数ジェネレーターを作成するにはどうすればよいですか? (たとえば、C/C++ Java)

33
Rella

このアルゴリズムもあります:

enter image description here

ああ、もっと真剣に:

乱数ジェネレーターは、数値のセットを別の数値に転送する数式を使用します。たとえば、定数Nと別の数値n_0を使用し、n mod N(モジュロ演算子)の値を取得すると、新しい数値n_1n_0とは無関係であるかのように見えます。ここで、n_1を使用して同じプロセスを繰り返すと、別の番号が取得されます。ここにあるのは、一見乱数の(非常に悪い)ジェネレータです。

ここで説明した方法はおもちゃの方法であり、深刻なものには使用しないでください。ただし、一般的な原則を示しています。

また注意してください:

悪いRandsが原因で結果が疑わしいすべての科学論文が図書館の棚から消えると、各棚には拳と同じくらいの隙間ができます。

数値レシピ )の第7章からの言い換え。これは、深刻な作業に乱数ジェネレーターを使用する人にとって必読のテキストです。

21
Boris Gorelik

留意すべきことの1つは、「真の」乱数ジェネレーターがないことです。彼らはただの人間をランダムにlookする数字を生成するだけです。

これの最も簡単な例の1つは(同様に実装するために) Linear congruential generator です。確かに、数字はあなたと私には予測できないように見えますが、実際には有限のフィールド内で等間隔になっています。

もちろん、 Blum Blum Shub のような一部のジェネレーターは、部外者が深刻な数学スキルと計算能力をタスクに適用しても予測できませんが、基本的なレベルでは、乱数ジェネレーターはそうではありませんランダム;定期的で予測可能です。

18

昔の私がそれらを作ったのは、システムから非常に急速に変化する値、たとえばシステムミリ秒タイマーを取得することでした。

次に行う必要があるのは、この「入力」番号から新しい番号を生成する数式を適用し、必要な範囲、たとえば0..255にクリップすることです。

random_number = integer(formula(timer-value))MOD 255

そうすれば、関数を呼び出すたびに新しい「ランダムな」番号を取得できます。

数式関数の例は次のとおりです。
formula(x)=((x XOR constant)+ constant2)MOD範囲
XORはかつて私のお気に入りの1つでした。


更新:この式は非常に悪いものであり、かなり予測可能な数のセットを生成することを認識しています。また、システムタイマーはソースとして予測しすぎます。したがって、ほとんどのアプリケーションでは、これで十分ではありません。より良いランダム性が必要な場合は、システムタイマーと better formulas よりも多くのソースを使用してそれらを組み合わせます。

5
thomaspaulb

私はJava用にこれを見つけました:

http://www.javamex.com/tutorials/random_numbers/Java_util_random_algorithm.shtml

グーグルで ランダム関数のJavaの動作

答えは言語固有であると確信していますが、選択した言語に合わせてGoogleクエリを変更してみてください。

3
David

彼らがどのように働いているかについて利用可能な多くの情報があります...コナミマンの答えを見て、グーグルを少し使ってください。

なぜ新しいランダムジェネレーターを作成したいのですか?非常に特別なものが必要になるまで、おそらくそうしようとすべきではありません。たとえば、ゲームでは shuffle bag を使用して「公正な」ランダム値を生成できます。 SOに関するこの興味深い質問 をご覧ください。
最初に読んだときにアイデアと実装が本当に気に入ったので、ここに投稿します:)

1
tanascius

これは、サイコロを転がすためのコードです。乱数発生器を使用します。このRNGのパッドは、16個の16進数値を保持します。

 DIM pad(15) AS INTEGER
CLS
Egg$ = "EFCDBA01457FA968"
  ghh$ = Egg$
 nom% = 0
zen% = LEN(ghh$)
WHILE zen% > 0
opp$ = LEFT$(ghh$, 1)
eff% = ASC(opp$)
IF eff% >= 48 AND eff% <= 57 THEN eff% = eff% - 48 ELSE eff% = (eff% - 65) + 10
IF eff% > 15 THEN eff% = eff% - 32
pad(nom%) = eff%
nom% = nom% + 1
zen% = LEN(ghh$) - 1
ypp$ = RIGHT$(ghh$, zen%)
ghh$ = ypp$
WEND
sol& = 0
FOR zyx% = 0 TO 3
sol& = sol& * 16
sol& = sol& + pad(zyx%)
NEXT zyx%
sat% = sol& - 32768
RANDOMIZE sat%
FOR zyx% = 0 TO 15
PRINT HEX$(pad(zyx%));
NEXT zyx%
RANDOMIZE TIMER
respawn:
INPUT "sides per die"; die%
INPUT " number of dice"; dice%
INPUT "number to add to dice roll can be negative"; num%
INPUT "multiplier use 1 if so desired single precision floating point number"; g!
PRINT " hit any key to roll again with these values hit n for new values and q to quit"
PRINT " the number will be added or subtracted first before the multiplier takes effect"
reroll:
sum! = 0
FOR x% = 1 TO dice%
GOSUB rndmz
GOSUB demf
GOSUB drand
k% = INT(dr# * die%) + 1
sum! = sum! + k%
NEXT x%
sum! = (sum! + num) * g!
PRINT "you rolled a :"; sum!
i$ = ""
WHILE i$ = "": i$ = INKEY$: WEND
IF i$ = "n" THEN GOTO respawn
IF i$ = "q" THEN GOTO theend
GOTO reroll
theend:
SYSTEM
END
rndmz: rhet$ = ""
zum% = 0
FOR yxz% = 0 TO 15
FOR zyx% = 0 TO 15
IF zyx% MOD 3 = 0 THEN zum% = (zum% + pad(zyx%)) MOD 16
IF zyx% MOD 3 = 1 THEN zum% = (zum% + 16 - pad(zyx%)) MOD 16
IF zyx% MOD 3 = 2 THEN zum% = (zum% + INT(RND * 16)) MOD 16
NEXT zyx%
rhet$ = rhet$ + HEX$(zum%)
NEXT yxz%
ghh$ = rhet$
RETURN
demf: nom% = 0
zen% = LEN(ghh$)
WHILE zen% > 0
opp$ = LEFT$(ghh$, 1)
eff% = ASC(opp$)
IF eff% >= 48 AND eff% <= 57 THEN eff% = eff% - 48 ELSE eff% = (eff% - 65) + 10
IF eff% > 15 THEN eff% = eff% - 32
pad(nom%) = eff%
nom% = nom% + 1
zen% = LEN(ghh$) - 1
ypp$ = RIGHT$(ghh$, zen%)
ghh$ = ypp$
WEND
FOR zyx% = 0 TO 15
'PRINT HEX$(pad(zyx%));
NEXT zyx%
RETURN
drand: dr# = pad(0)
FOR eff% = 1 TO 15
dr# = dr# / 16
dr# = dr# + pad(eff%)
NEXT eff%
dr# = dr# / 16
RETURN
derf: a# = 1
x# = 1
b# = 1 / (2 ^ .5)
c# = .2500000000000011#
FOR u% = 1 TO 3
y# = a#
a# = (a# + b#) / 2
b# = (b# * y#) ^ .5
c# = c# - x# * (a# - y#) ^ 2
x# = 2 * x#
pi# = ((a# + b#) ^ 2) / (4 * c#)
PRINT pi#
NEXT u%
pi# = pi# + .000000000000015#
PRINT pi#

これはここで最後に、アルゴリズムをわずか3ループで可能な限り多くの場所にpiを計算します。それは古くて基本的な言語で書かれていることを申し訳なく思っています
このロジックを注意深く見て、特にプライミングまたはシード/初期化手順に注意してください。これらは使用する必要があります。そうしないと、良いゲームとして失敗します。巨大なセキュリティを確保することは、速度と同じくらい重要ではありません...

0
John Einem

また、現在のクロック時間の5番目の10進数のようなものを使用して、これらのタイプのジェネレーターをシードすることも一般的です。いくつかのカオスシステムからの入力を一緒に追加します。気象データ、株式市場データ、ここでもモジュラスを使用すると、適切なシード数が得られます。

0
user3918295