2010-12-25 6 views
16

私はちょっと混乱しています。私は乱数を生成するためにRandomクラスを使うことができると知っていますが、8バイトの数値を指定して生成する方法はわかりません。Javaで8バイトの数字を生成

おかげで、 Vukの

答えて

13

あなたはjava.util.Randomクラスはので、すべての8バイト値(64ビットのシーケンス)は、このクラスを使用して生成することができない、48ビットのシードを使用していることに注意してください。このような状況では、SecureRandomnextBytes methodを使用することをお勧めします。

この使用法は、java.util.Randomソリューションと非常によく似ています。ここで

SecureRandom sr = new SecureRandom(); 
byte[] rndBytes = new byte[8]; 
sr.nextBytes(rndBytes); 

48ビットの種子が十分でない理由です:

  • Randomクラスはそれが決定的であることを意味し、擬似乱数生成器を実装しています。
  • Randomの現在の「状態」は、将来のビットシーケンスを決定します。
  • 2つの州を持っているので、2つ以上の可能性のある未来のシーケンスはであることはできません。
  • 8バイトの値が2 の可能性があるため、これらの可能性の一部はRandomオブジェクトから読み取られません。 @Peter Lawreys excellent answerに基づいて

、それはより多くのupvotesに値する!):ここでは2 × 48ビットのシードとjava.util.Randomを作成するためのソリューションです。つまり、すべての可能なlongを生成できるjava.util.Randomインスタンスです。

class Random96 extends Random { 
    int count = 0; 
    ExposedRandom extra48bits; 

    class ExposedRandom extends Random { 
     public int next(int bits) { // Expose the next-method. 
      return super.next(bits); 
     } 
    } 

    @Override 
    protected int next(int bits) { 
     if (count++ == 0) 
      extra48bits = new ExposedRandom(); 
     return super.next(bits)^extra48bits.next(bits) << 1; 
    } 
} 
+0

すべての単一の答えの下に同じコメントを残すことは涼しくありません。 – Roman

+2

なぜですか?私はそれが大丈夫だと思う。これは私がコメントしたそれぞれの回答に当てはまります。 – aioobe

+0

私の直感的な解決策は、2つの4バイト値を生成することでした。私が正しく理解していれば、同じジェネレーターを2回使用すると、2つの値が除外される(または少なくともそうでない可能性がある)ので、これは機能しません。例えば。 FF FFはFF AAと同じではありませんか?私はPRGがどのように実装されているのかわからないので、これは私が各数値が以前の数値と(擬似)独立していると思うので私に驚きました。 – zockman

5

それがいずれかの長さ8のバイト配列で行うことができる。

byte[] byteArray = new byte[8];  
random.nextBytes(byteArray); 

またはタイプlongの変数(8バイトの数を表す):

long randomLong = random.nextLong(); 
+2

これらの2つの選択肢のどちらも、可能な8バイト値。私の答えを見てください。 – aioobe

+0

@aioobe:理由を説明できますか?私はドキュメントを読んだことがあり、実装を読みましたが、私はまだ分かりません。かなり複雑な(数学ベースの)アルゴリズムがあり、わかっているように、それは依存する値を生成します。そしてそれが本当であれば、1つのランダムなインスタンスは本当にすべてのlong値を生成するわけではありません。しかし、異なる「ランダム」(異なる「開始点」を持つ)があります。私は正しい? – Roman

+0

私の答えを更新しました。 – aioobe

0

少し調整コードhere

import java.util.Random; 

/** Generate 10 random integers in the range 0..99. */ 
public final class RandomByte { 

    public static final void main(String... aArgs){ 
    log("Generating 10 random integers in range 0..255."); 

    //note a single Random object is reused here 
    Random randomGenerator = new Random(); 
    for (int idx = 1; idx <= 10; ++idx){ 
     int randomInt = randomGenerator.nextInt(256); 
     // int randomInt = randomGenerator.nextBytes(256); 
     log("Generated : " + randomInt); 
    } 

    log("Done."); 
    } 

    private static void log(String aMessage){ 
    System.out.println(aMessage); 
    } 
} 

さらにいくつかの読書は:Math.random() versus Random.nextInt(int)

+0

'Random'クラスは8バイトの値をすべて生成できないことに注意してください。 – aioobe

2

longタイプはそうRandom.nextLong()はあなたがやりたいように見える、8バイトの符号付き整数です。あなたは結果としてバイト配列が必要な場合または:

byte[] result = new byte[8]; 
Random.nextBytes(result); 
+1

'Random'クラスはすべての可能なlongを生成できないことに注意してください。 – aioobe

11

私は@aioobe 'point aboutランダムに48ビットシードを使用していることに同意します。 SecureRandomは優れたソリューションです。しかし、OPクラスのRandomクラスの使用方法に関する質問に答えるには、可能なすべての8バイト値を許可してください。これは、シードを定期的にリセットすることです。

int counter = 0; 
Random rand = new Random(); 
Random rand2 = new Random(); 

if (++counter == 0) rand = new Random(); // reset every 4 billion values. 

long randomLong = rand.nextLong()^rand2.nextLong() << 1; 

ランダムは、2^47の長い値のシーケンスのみを許可します。 2つのランダムジェネレータを使用することで、シーケンス内でジャンプし続けると、2^47 * 2^47の可能な値が2つ得られます。 < < 1の使用は、同じシードを持つ両方のランドームを持つことによる影響を回避することです(この場合、^は40億の値に対して0を連続して生成します)。

+0

+1、素晴らしい答え。リセットと左シフトに関する興味深いメモ!無作為の無名サブクラスでRandomインスタンスをカプセル化した方が良いと思います。 – aioobe

+0

2つのランダムオブジェクトは、両方とも同じシードを持つように正確に同じ乱数を作成しませんか? (すなわち、高速コンピュータではSystem.currentTimeMillis()は両方で同じになるでしょうか?) –

+0

trueの古いバージョンのJavaでは。 Java 5.0から、RandomはSystem.nanoTime()とAtomicLongカウンタを使用します。 –

関連する問題