17

まず、ランダムアクセス乱数ジェネレーターのようなものがあります。rand100()が常に0〜100の値を生成すると仮定すると、これまでのように乱数を順次生成できるだけではありません。

for (int i=0;i<5;i++)
   print rand100()

output: 
14
75
36
22
67

ただし、次のようなランダムな値にもランダムにアクセスします。

シードを変更しない限り、rand100(0)は14を出力します

rand100(3)は常に22を出力します

rand100(4)は常に67を出力します

等々...

これを行うオープンソースのジェネレーターアルゴリズムを実際に見つけましたが、シードを変更することはできません。疑似ランダム性は複雑な体であることを私は知っています。その機能を追加するためにそれを変更する方法がわかりません。

シード可能なランダムアクセス乱数ジェネレーター、できればオープンソースはありますか?または、これについてもっと良い用語がありますか?詳細についてはグーグルで検索できますか?

そうでない場合、私の質問のパート2は、信頼できるランダムなオープンソースの従来のシード可能な疑似乱数ジェネレーターがあるので、特定のシードの各プラットフォームの値の一貫したシーケンスを保持しながら、複数のプラットフォーム/言語に移植できますか?

4

8 に答える 8

7

そのようなことは聞いたことがありませんが、まともなハッシュを使用して、シード値と「インデックス」を取得し、それらをハッシュ関数で実行するラッパー関数を作成できるようです。さまざまな暗号化ハッシュ関数によって出力されるビットのランダム性はわかりませんが、誰かがそれを調べたと思います。

于 2010-06-10T23:19:57.247 に答える
5

Blum Blum Shubは、生成する任意の値へのシードとランダムアクセスを備えた疑似乱数ジェネレータです。

于 2013-10-22T02:39:13.470 に答える
5

疑似乱数ジェネレータのPCGファミリは、対数時間で前後にジャンプできます(つまり、1000の数値を前方にジャンプするには、O(log(1000))操作が必要です)。これは、ランダムアクセスと見なすのに十分です。リファレンスCとC++の実装は、どちらもこの機能をサポートしています。

PCGサイトのフロントページの表は、他の多くのジェネレーターがジャンプアヘッドをサポートできることを示していますが、どの実装でもそれを見たことがありません。

于 2016-07-21T05:10:16.213 に答える
3

すべての返信に感謝します。また、同様の質問をしたときに発生する可能性のある人のために、私が求めていたものとは正確には一致しないが、私の目的に合った解決策を見つけました。

ここで見つけることができるのはパーリンノイズクラスです。計画されているプラ​​ットフォームの1つがAndroidであるため、これが従来の乱数ジェネレーターと比較して計算がどれほど複雑かはわかりません。これは懸念事項です。また、パーリンノイズは疑似ランダム性と同じものではありませんが、私が知る限り、高いオクターブおよび/または周波数値は、真のランダム性の統計的レベルがそれほど重要ではない非暗号化目的に適したランダム性を提供するはずです。ランダム性の単なる出現として。

このソリューションでは、シードが可能であり、任意のポイントからランダムセットをサンプリングすることもできます。つまり、ランダムアクセスのランダム性です。

比較のために、左側の列に通常のc ++ランダム性(rand%200)のセットの例を示し、右側にパーリンノイズ(%200に相当)を示します。

91 , 100
48 , 97
5 , 90
93 , 76
197 , 100
97 , 114
132 , 46
190 , 67
118 , 103
78 , 96
143 , 110
187 , 108
139 , 79
69 , 58
156 , 81
123 , 128
84 , 98
15 , 105
178 , 117
10 , 82
13 , 110
182 , 56
10 , 96
144 , 64
133 , 105

両方とも0にシードされました

パーリンノイズのパラメータは

octaves = 8
amplitude = 100 
frequency = 9999
width/height = 10000,100

パーリンノイズの順次サンプリング順序は単純でした

for (int i=0;i<24;i++)
    floor(Get(i,i)+100);
//amplitude 100 generates noise between -100 and 100, 
//so adding 100 generates between 0 and 200
于 2010-06-11T01:04:09.237 に答える
3

グーグルで働いていた人からの本当に良いブログ投稿を読んだことがあります。それはあなたと非常によく似た質問に答えました。

要するに、答えは、暗号化キーとして乱数を使用し、暗号化するデータとしてシーケンスに必要な番号のインデックスを使用するブロック暗号を使用することでした。彼は、任意のサイズ(ビット単位)のブロックで機能する暗号について言及しました。これは便利です。暗号の名前を見つけるには、ブログを検索する必要があります。

例:0から(2 ^ 32)-1までの整数のランダムなシャッフルが必要だとします。これは、4バイトの入力を受け取り、4つの暗号化されたバイトを返すブロック暗号を使用して実現できます。シリーズを反復処理するには、最初に値0、次に1、次に2などのブロックを「暗号化」します。シャッフルされたシーケンスの100万番目のアイテムのみが必要な場合は、数値1,000,000を暗号化します。

暗号を使用して取得する「ランダムシーケンス」は、ハッシュ関数を使用して取得するものとは異なります(@MichaelBurrが提案したように)。暗号を使用すると、整数の範囲のランダム順列を取得し、その順列内の任意のアイテムを一定時間でサンプリングできます。つまり、「乱数」は繰り返されません。ハッシュ関数を使用すると、シーケンス内の番号が繰り返される場合があります。

そうは言っても、@ MichaelBurrのソリューションはあなたの状況により適しているので、それを使用することをお勧めします。

于 2012-08-05T13:25:17.347 に答える
1

これを実現する1つの方法は、小さなセットから大量のランダムデータを合成することです。これを行う1つの方法は、事前に生成されたランダムデータの3つの配列を用意することです。各配列には素数の全体が必要です。

乱数を生成するために、これらのワンタイムパッドのそれぞれが無限にループされ、増分的にサンプリングされることを想像します。xorを使用してそれぞれのデータを結合します。

#define PRIME1 7001
#define PRIME2 7013
#define PRIME3 7019

static int pad1[PRIME1];
static int pad2[PRIME2];
static int pad3[PRIME3];

static void random_no_init (void)
{
  static int initialized = 0;
  int i;
  if (initialized)
    return;
  for (i = 0; i < PRIME1; i++) pad1[i] = random ();
  for (i = 0; i < PRIME2; i++) pad2[i] = random ();
  for (i = 0; i < PRIME3; i++) pad3[i] = random ();

  initialized = 1;
}

int random_no (int no)
{
   random_no_init ();
   return pad1[no % PRIME1] ^ pad2[no % PRIME2] ^ pad3[no % PRIME3];
}

上記のコードサンプルは、ランダムにアクセス可能な344618953247全体を生成する簡単な例を示しています。実行間で再現性のある結果を保証するには、乱数ジェネレーターにシードを提供する必要があります。異なる素数の選択に基づくシードバリエーションを使用して同じ原理に基づいて構築されたより複雑なシステムは、 http: //git.gnome.org/browse/gegl/tree/gegl/gegl-random.cにあります。

于 2012-12-20T03:07:37.300 に答える
0

私が知っているすべてのジェネレーターは反復的です。したがって、「ランダムアクセス」には、最初の値から要求した値までのすべての値を計算することが含まれます。

最も近い方法は、固定シードを取得してハッシュし、次に、非常に熱心に混合するものを使用してインデックス値をハッシュすることです。

または、それらの長いリストを生成して保存します。

于 2010-06-10T23:25:11.103 に答える
0

この特許をご覧ください:ランダムアクセス疑似乱数ジェネレーター https://patents.google.com/patent/US4791594

マルチステージビットスクランブリングスキームを使用して、ランダムにアクセスできる疑似番号シーケンスを生成します。

入力アドレスを制御ビットとして使用して複数のシード番号をスクランブリングし、結果をXORして出力を生成し、前のパスから生成された結果を使用してスクランブリングの2番目のパスを作成するという考え方です。

于 2018-03-29T15:26:56.603 に答える