サーチ…


備考

本当にランダムなものは何もないので、javadocはこれらの数値を疑似乱数と呼びます。これらの数値は擬似乱数ジェネレータで生成されます。

疑似乱数

Javaはutilsパッケージの一部として、適切にRandomという名前の基本擬似乱数ジェネレータを提供します。このオブジェクトは、任意の組込み数値データ型( intfloatなど)として疑似乱数値を生成するために使用できます。また、これを使用して、ランダムなブール値、またはランダムなバイト配列を生成することもできます。使用例は次のとおりです。

import java.util.Random;  

...
  
Random random = new Random();
int randInt = random.nextInt();
long randLong = random.nextLong();

double randDouble = random.nextDouble(); //This returns a value between 0.0 and 1.0
float randFloat = random.nextFloat(); //Same as nextDouble

byte[] randBytes = new byte[16];
random.nextBytes(randBytes); //nextBytes takes a user-supplied byte array, and fills it with random bytes. It returns nothing.

注:このクラスは、かなり低品質の擬似乱数しか生成しません。暗号演算などの乱数生成には使用しないでください。高品質のランダム性が重要な場合は、 SecureRandomクラスを使用します。以下に述べるように)。 「安全」と「安全でない」ランダム性の区別についての説明は、この例の範囲外です。

特定範囲の疑似乱数

Random nextInt(int bound)メソッドは、上位の排他的境界、つまり返される乱数値がより小さい数を受け取ります。ただし、 nextIntメソッドだけがバインドを受け入れます。 nextLongnextDoubleなどしないでください。

Random random = new Random();
random.nextInt(1000); // 0 - 999

int number = 10 + random.nextInt(100); // number is in the range of 10 to 109

Java 1.7 ThreadLocalRandomsource )を使用することもできます。このクラスは、スレッドセーフPRNG(擬似乱数ジェネレータ)を提供します。このクラスのnextIntメソッドは、上限と下限の両方を受け入れることに注意してください。

import java.util.concurrent.ThreadLocalRandom;

// nextInt is normally exclusive of the top value,
// so add 1 to make it inclusive
ThreadLocalRandom.current().nextInt(min, max + 1);

公式文書では、 boundが2 30 +1(emphasis added)に近い場合、 nextInt(int bound)は変なことを行うことができることに注意しください。

アルゴリズムはややこしい。 これは、 (2 ^ 31がnで割り切れないという事実のために) 不均一な分布をもたらす値を拒絶する 。値が拒絶される確率はnに依存する。 最悪のケースは、n = 2 ^ 30 + 1であり、それに対して、拒絶の確率は1/2であり、ループ終了前の予想反復回数は2である。

つまり、バインディングを指定するとnextIntメソッドのパフォーマンスが低下しますが、このパフォーマンスの低下は、 boundがmax int値の半分に近づくほど顕著になります。

暗号的に安全な擬似乱数の生成

RandomThreadLocalRandomは、日々の使用には十分ですが、大きな問題があります。 線形合同ジェネレータは、出力がかなり簡単に予測できるアルゴリズムです。したがって、これらの2つのクラスは、暗号の使用(キー生成など)に適していません

予測が非常に困難なPRNGが必要な状況でjava.security.SecureRandomを使用することができます。このクラスのインスタンスによって作成された乱数を予測することは、クラスを暗号的に安全なものとしてラベル付けするほど難しいです。

import java.security.SecureRandom;
import java.util.Arrays;

public class Foo {
    public static void main(String[] args) {
        SecureRandom rng = new SecureRandom();
        byte[] randomBytes = new byte[64];
        rng.nextBytes(randomBytes); // Fills randomBytes with random bytes (duh)
        System.out.println(Arrays.toString(randomBytes));
    }
}

SecureRandomは、暗号的に安全であることに加えて、2 48の Random期間と比較して、2 160という巨大な期間を持っています。これは、よりかなり遅いことの一つの欠点があるRandomとのような他の線形のPRNG メルセンヌツイスターXorshiftをしかし、。

SecureRandom実装は、プラットフォームとプロバイダの両方に依存します。デフォルトのSecureRandomsun.security.provider.SecureRandom SUNプロバイダによって指定されsun.security.provider.SecureRandom ):

  • Unixのようなシステムでは、 /dev/random/dev/urandomからのデータがシードされています。
  • Windowsでは、 CryptoAPIの CryptGenRandom()呼び出しがシードされています。

重複のない乱数を選択する

/**
 * returns a array of random numbers with no duplicates
 * @param range the range of possible numbers for ex. if 100 then it can be anywhere from 1-100
 * @param length the length of the array of random numbers
 * @return array of random numbers with no duplicates.
 */
public static int[] getRandomNumbersWithNoDuplicates(int range, int length){
    if (length<range){
        // this is where all the random numbers
        int[] randomNumbers = new int[length];
        
        // loop through all the random numbers to set them
        for (int q = 0; q < randomNumbers.length; q++){
            
            // get the remaining possible numbers
            int remainingNumbers = range-q;
            
            // get a new random number from the remainingNumbers
            int newRandSpot = (int) (Math.random()*remainingNumbers);
            
            newRandSpot++;
            
            // loop through all the possible numbers
            for (int t = 1; t < range+1; t++){
                
                // check to see if this number has already been taken
                boolean taken = false;
                for (int number : randomNumbers){
                    if (t==number){
                        taken = true;
                        break;
                    }
                }
                
                // if it hasnt been taken then remove one from the spots
                if (!taken){
                    newRandSpot--;
                    
                    // if we have gone though all the spots then set the value
                    if (newRandSpot==0){
                        randomNumbers[q] = t;
                    }
                }
            }
        }
        return randomNumbers;
    } else {
        // invalid can't have a length larger then the range of possible numbers
    }
    return null;
}

このメソッドは、要求された長さのサイズを持つ配列をループし、残りの長さを見つけることによって機能します。これらの可能な番号の乱数をnewRandSpotに設定し、その番号を未取得の数の中に見つけます。これは、範囲をループし、その番号がすでに取得されているかどうかを確認することによってこれを行います。


たとえば、範囲が5で長さが3で、すでに2を選択している場合は残りの4つの数字があるので、1と4の間の乱数を取得し、任意の数をスキップする範囲(5)をループします私たちはすでに使用しています(2)。

今度は、1と4の間で選択された次の数字が3であるとしましょう。最初のループでは、まだ取り出されていない1が得られます。3から1を取り除くことができます。2.今度は2番目のループで、私たちは何もしません。私たちは4になるまでこのパターンに従います.1を削除すると0になりますので、新しいrandomNumberを4に設定します。

指定されたシードで乱数を生成する

//Creates a Random instance with a seed of 12345.
Random random = new Random(12345L);

//Gets a ThreadLocalRandom instance
ThreadLocalRandom tlr = ThreadLocalRandom.current();

//Set the instance's seed.
tlr.setSeed(12345L);

同じシードを使用して乱数を生成すると、毎回同じ数値が返されるため、重複した数字になりたくない場合は、すべてのRandomインスタンスに対して異なるシードを設定することをお勧めします。

すべての呼び出しで異なるLongを取得する良い方法は、 System.currentTimeMillis()です。

Random random = new Random(System.currentTimeMillis());
ThreadLocalRandom.current().setSeed(System.currentTimeMillis());

apache-common lang3を使って乱数を生成する

org.apache.commons.lang3.RandomUtilsを使用して、1行で乱数を生成することができます。

int x = RandomUtils.nextInt(1, 1000);

nextInt(int startInclusive, int endExclusive)メソッドは範囲をとります。

intとは別に、このクラスを使用してlongdoublefloatおよびbytesをランダムに生成できbytes

RandomUtilsクラスには次のメソッドが含まれています。

static byte[] nextBytes(int count) //Creates an array of random bytes.
static double nextDouble() //Returns a random double within 0 - Double.MAX_VALUE
static double nextDouble(double startInclusive, double endInclusive) //Returns a random double within the specified range.
static float nextFloat() //Returns a random float within 0 - Float.MAX_VALUE
static float nextFloat(float startInclusive, float endInclusive) //Returns a random float within the specified range.
static int nextInt() //Returns a random int within 0 - Integer.MAX_VALUE
static int nextInt(int startInclusive, int endExclusive) //Returns a random integer within the specified range.
static long nextLong() //Returns a random long within 0 - Long.MAX_VALUE
static long nextLong(long startInclusive, long endExclusive) //Returns a random long within the specified range.


Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow