6

1 ~ 10000 の範囲の乱数を重複なく連続して生成する必要があります。推奨事項はありますか?

説明: Sqlite DB にレコードを保持するアプリケーションの新しいバージョンを作成しています。アプリケーションの最後のバージョンでは、各レコードに一意のキーがありませんでした。しかし、アップグレードされた新しいバージョンでは、以前のバージョンの DB からのインポート機能をサポートする必要があります。つまり、古い DB からすべてのレコードを読み取り、一意のキーの乱数を生成して新しい DB に格納します。ここでは、最大 10000 レコードを継続的にインポートする必要があります。

4

14 に答える 14

5

繰り返しなしで 1 から 10,0000 の範囲内にある必要があるが、シーケンシャルでない場合は、最初に 10000 要素のシーケンシャル配列を作成してから、それらをシャッフルするのがおそらく最善でしょう。

ただし、元の質問に対するコメントには同意する必要があります。それらをノンシーケンシャルにすることには何の価値もありません。

代わりに、一意で非順次が重要であり、1 から 10,000 の範囲が疑わしくなります。GUID を使用するのがおそらく最善でしょう。

于 2008-10-10T20:45:14.133 に答える
5

最終的には、それらの生成を停止するか、スターを複製する必要があります。

コンピューターでは、オプションは疑似乱数ジェネレーター (PRNG) にかなり制限されており、繰り返さないという制約がある場合、PRNG が最適なオプションです。実際のランダムデータは数値を複製することがあります。

あなたの場合、大きな PRNG (32 ビット以上) を使用して 10,000 の数字をシャッフルし、シャッフルされた順序で数字を送信することを検討します。

それらが使い果たされたら、再びシャッフルできます。PRNG は非常に大きいため、シーケンスを複製する前に 10,000 の数字を何度も調べることができます。

あなたの行動についてもっと情報を提供してください。より良い答えが見つかるかもしれません。

-アダム

于 2008-10-10T04:44:06.957 に答える
5

Mersenne Twister は現在最高です (ただし、新しい発見には数週間遅れている可能性があります)。ほぼすべての言語のソースがどこかで入手可能であり、MT も Boost で提供されています。

于 2008-10-10T04:44:44.317 に答える
3

ブーストはおそらく、数値が繰り返されないことを保証する何かを行います。しかし、ちょっとした楽しみとして、ここに私の考えがあります。

注: 私は自分のランドをその方向に生成しようとはしません。

#include <iostream>
#include <vector>
#include <algorithm>


class GaranteedNoRepeatRandom
{
    public:
        GaranteedNoRepeatRandom(int limit)
            :data(limit)
            ,index(0)
        {
            for(int loop=0;loop < limit;++loop)
            {   data[loop]  = loop;
            }
            // Note: random_shuffle optionally takes a third parameter
            // as the rand number generator.
            std::random_shuffle(&data[0],&data[0]+limit);
        }

        unsigned int rand()
        {
            unsigned int result = data[index];
            index   = (index+1) % data.size();

            // Add code to re-shuffle after index wraps around
            return result;
        }
    private:
        std::vector<unsigned int>               data;
        std::vector<unsigned int>::size_type    index;
};

int main()
{
    GaranteedNoRepeatRandom     gen(10000);

    for(int loop =0;loop < 10;++loop)
    {
        std::cout << gen.rand() << "\n";
    }
}
于 2008-10-10T05:05:14.667 に答える
3

TR1 は乱数を適切にサポートしています (コンパイラがサポートしている場合)。

そうでなければブースト

それが基本的にTR1になったものです。

重複しない限り、シャッフルが必要です。かなり単純ですが、正しく行わないと、いくつかの落とし穴があります。Jeff Atwood は、しばらく前に素晴らしい記事を書きました。

http://www.codinghorror.com/blog/archives/001015.html

于 2008-10-10T04:45:44.627 に答える
2

データベース レコードの一意のキーとして乱数を使用するという考え全体に疑問を呈してもよろしいですか? 私は sqlite に詳しくありませんが、何らかの一意の列識別子を内部でサポートしているかどうかを調査する価値があります。たとえば、SQL Server には「ID」列があり、Oracle には「シーケンス」があり、どちらも同じ目的を果たします。

于 2008-10-10T05:13:13.980 に答える
2

Boost.Randomは良い選択であり、私にとってはうまく機能します。ただし、多くの乱数ジェネレーターとディストリビューションが必要ない場合は、Boost パッケージ全体をインストールするのではなく、別のライブラリを探すことができます。

于 2008-10-10T04:44:47.297 に答える
2

どのようにランダムですか?明らかに rand() があり、OS 固有のものもあります (たとえば、Windows には CryptoAPI に何かがあります)。何かを書いていますか (推奨されません)、それとも既存の関数を探しているだけですか?

于 2008-10-10T04:45:01.913 に答える
2

mtrandいいですね。

于 2008-10-10T04:46:10.977 に答える
2

大きな乱数を生成します。128 ビットと言います。このような 2 つの数値が 10000 のセットで同じである確率は、途方もなく小さいです (n^2/2^b のオーダーで、n = 必要な数値の数、b = 使用されるビットの数)。十分なビット数が与えられれば、オッズは宇宙線によって RAM が破損してアルゴリズムが失敗するオッズよりも小さくなります。乱数を描画するスペースに、探しているビット数が実際にあることに注意してください。32 ビットのプールから誤って 128 ビットの数値を生成するのは簡単です (つまり、1 から 2^128 までの数値を生成している場合でも、2^32 の可能性しかありません)。ブースト ライブラリの乱数ジェネレーターは、これを正しく行うことができます。ところで: 128 ビットが気に入らない場合は、次に、ハッシュの衝突が実際に発生する可能性がないと確信できるまで、256 ビット以上を使用します。これを一度だけ行う必要がある場合は、前の回答で既に述べたシャッフル方法を使用してください。これには、完全なハッシュを生成するという利点があります。

于 2008-10-10T17:17:20.073 に答える
2

繰り返さない一連の値を生成する必要がある場合でも、結果を「ランダム」と呼ぶことはできません。真のランダム性は、シーケンス内の値の分布と関係があるよりも、繰り返しの欠如とは関係ありません。

于 2008-10-10T17:51:34.030 に答える
2

乱数の生成は、偶然に任せるにはあまりにも重要です。-- Robert R. Coveyou、オークリッジ国立研究所

于 2008-10-14T12:01:14.017 に答える
0

Numerical Recipes in Cには、乱数生成に特化した章全体があります。そこにはいくつかの実装があります。シンプルで単純なものから、優れた統計的特性を備えた複雑なものまで。

于 2008-10-10T05:10:15.623 に答える
0

http://random.org/本当に乱数が必要な場合

于 2008-10-10T17:20:08.540 に答える