C仕様では、Rand()
の特定の実装に関する仕様が提供されていないことを理解しています。さまざまな主要プラットフォームで一般的に使用されているさまざまなアルゴリズムは何ですか?それらはどのように異なりますか?
この記事を参照してください: http://en.wikipedia.org/wiki/List_of_random_number_generators
これはglibcのRand()
のソースコードです。
/* Reentrant random function from POSIX.1c.
Copyright (C) 1996, 1999, 2009 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <[email protected]>, 1996.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <stdlib.h>
/* This algorithm is mentioned in the ISO C standard, here extended
for 32 bits. */
int
Rand_r (unsigned int *seed)
{
unsigned int next = *seed;
int result;
next *= 1103515245;
next += 12345;
result = (unsigned int) (next / 65536) % 2048;
next *= 1103515245;
next += 12345;
result <<= 10;
result ^= (unsigned int) (next / 65536) % 1024;
next *= 1103515245;
next += 12345;
result <<= 10;
result ^= (unsigned int) (next / 65536) % 1024;
*seed = next;
return result;
}
ソース: https://sourceware.org/git/?p=glibc.git;a=blob_plain;f=stdlib/Rand_r.c;hb=HEAD
ご覧のとおり、加算とシフトを掛けるだけです。値は慎重に選択され、Rand_MAXの反復で出力が繰り返されないようにします。
これは古い実装であり、より複雑なアルゴリズムに置き換えられていることに注意してください。 https://sourceware.org/git/?p=glibc.git;a=blob_plain;f=stdlib/random_r.c; hb = HEAD
リンクが壊れている場合は、「glibcRand_r」のGoogle
私はかつて、離散数学のコースのCRNGに関するレポートを作成しました。そのために、msvcrt.dllのRand()を逆アセンブルしました。
msvcrt.dll:77C271D8 mov ecx, [eax+14h]
msvcrt.dll:77C271DB imul ecx, 343FDh
msvcrt.dll:77C271E1 add ecx, 269EC3h
msvcrt.dll:77C271E7 mov [eax+14h], ecx
msvcrt.dll:77C271EA mov eax, ecx
msvcrt.dll:77C271EC shr eax, 10h
msvcrt.dll:77C271EF and eax, 7FFFh
つまり、(テストされていない)のようなLCGです...
int ms_Rand(int& seed)
{
seed = seed*0x343fd+0x269EC3; // a=214013, b=2531011
return (seed >> 0x10) & 0x7FFF;
}
PRNG(疑似乱数ジェネレーター)の分野は非常に広大です。
まず最初に、外部入力(通常は物理的)がないと、乱数の実際のソースを取得できないことを理解する必要があります。そのため、これらのアルゴリズムは疑似ランダムと呼ばれます。通常、 seemsランダムであるが、まったくランダムではない非常に長いシーケンスで位置を初期化するためのシード。
最も単純なアルゴリズムの1つは、Linear Congruential Generator( [〜#〜] lcg [〜#〜] )、長いシーケンスを保証するためのいくつかのコストラインがあり、それはまったく安全ではありません。
もう1つの面白いもの(少なくとも名前は)は、Blum Blum Shub Generator( [〜#〜] bbs [〜#〜] )です。これは、モジュロ演算のべき乗に依存しているため、通常のPRNGでは珍しいものです。シーケンスを破る際にRSAやElGamalなどの他のアルゴリズムに匹敵するセキュリティを提供します(その証拠がわからない場合も)
特定の、またはより高度なものが必要な場合は、さまざまな乱数ジェネレーターにBoostRandomライブラリを使用できます。
Boost Randomのドキュメントは ここ です。