4

真のランダムバイトのファイルがあります。ファイルからバイトを取得してスケーリングすることにより、指定された範囲のランダムな整数を返す関数が必要です。(これは正しい言葉ですか?)

public int getInt(int l, int h) throws IOException {
    int m = (h - l) + 1;            // number of ranges needed
    int r = 256 / m;                // size of byte range
    int x = (r * m) - 1;            // maximum allowable byte value
    int b;
    do {
        try {                       // get random byte from file
            b = ram.readUnsignedByte();
        } catch (EOFException e) {  // catch EOF, reset pointer
            b = 255; ram.seek(0);   // and set b to maximum value
        }                           // so test will fail.
    } while(b > x);                 // if byte is greater than
                                    // allowable value, loop.
    return (b / r) + l;             // return random integer
}                                   // within requested range

これが私の機能です。ファイルをスケーリングして、ファイル内のバイトの真のランダム性を破壊することを心配しています。許可された最大値を超える数値を破棄する必要があることを読みました(したがって、数値0〜9の場合、10の異なるグループに配布する値が7つしかないため、最大値は249になります)。私の実装は正しいように見えますか?

また、大きすぎる特定のバイトを無効にするだけで、何らかの方法で分布を歪めているのではないかと思います。

4

1 に答える 1

1

はい、バイアスを回避するために、モジュロを使用することはできません。範囲内にない結果を破棄する必要があります。

プログラミングを成功させる秘訣は、タスクを適切なサブタスクに分割することです。クイックスペック:

  1. 特定の数値を格納するために必要なビット数を計算する関数を追加します
  2. ランダム性ファイルからバイトを読み取ってバッファリングするクラスを追加し、ファイルから取得したビット数(残りのビットは0)の整数を取得するメソッドを備えています。
  3. 実際のメソッドを追加して、乱数を取得します。
    • 結果の範囲を計算し、そこから必要なビット数を計算します
    • ビットを取得し、下限を追加し、結果が上限を超えた場合に再試行するループ

ステップ2についての注意:最初の実装はかなり粗雑である可能性があります。たとえば、整数として4バイトを取得し、余分なビットをスローすることができます。後でこのクラスを最適化して、未使用のビットを保持し、次回それらを使用して、ランダムなビットを無駄にしないようにすることができます。本当に良いランダムビットを取得することは通常いくらか費用がかかるので、この最適化はおそらく真剣に使用する価値があります。

ビット演算については、たとえば、このSOの質問を参照してください: Java「ビットシフト」チュートリアル?

于 2012-12-04T12:27:18.657 に答える