配列 - java 乱数 重複
どのようにJavaで特定の範囲内のランダムな整数を生成するには? (20)
特定の範囲でランダムなint
値を生成するにはどうすればよいですか?
私は以下を試しましたが、それらはうまくいきません:
試行1:
randomNum = minimum + (int)(Math.random() * maximum);
// Bug: `randomNum` can be bigger than `maximum`.
試行2:
Random rn = new Random();
int n = maximum - minimum + 1;
int i = rn.nextInt() % n;
randomNum = minimum + i;
// Bug: `randomNum` can be smaller than `minimum`.
Java 7以降、
Random
使用しないでください。 ほとんどの用途では、選択した乱数ジェネレータがThreadLocalRandom
。
フォーク結合プールと並列ストリームの場合、SplittableRandom
使用しSplittableRandom
。
ジョシュア・ブロッホ。 効果的なJava。 第3版。
Java 8から始める
フォーク結合プールと並列ストリームの場合、通常は高速のSplittableRandom
を使用し、 Random
と比較してより優れた統計的独立性と均一性プロパティを持ちます。
範囲[0, 1_000]:
ランダムなint
を生成するには[0, 1_000]:
int n = new SplittableRandom().nextInt(0, 1_001);
[0, 1_000]:
範囲の値のランダムなint[100]
配列を生成するには[0, 1_000]:
int[] a = new SplittableRandom().ints(100, 0, 1_001).parallel().toArray();
ランダム値のストリームを返すには:
IntStream stream = new SplittableRandom().ints(100, 0, 1_001);
2番目のコード例は、次のように編集できます。
Random rn = new Random();
int range = maximum - minimum + 1;
int randomNum = rn.nextInt(range) + minimum;
nextint(n)メソッドを使用してminとmaxの差の乱数を生成し、minの数値を結果に追加します。
Random rn = new Random();
int result = rn.nextInt(max - min + 1) + min;
System.out.println(result);
JavaのMath.Random
クラスは0ベースです。 だから、あなたが次のようなことを書くなら、
Random rand = new Random();
int x = rand.nextInt(10);
x
は0-9
間になります。
したがって、以下の25
個の配列から、 0
(配列の底辺)とarray.length
間の乱数を生成するコードは次のようになります。
String[] i = new String[25];
Random rand = new Random();
int index = 0;
index = rand.nextInt( i.length );
i.length
は25
を返すので、 nextInt( i.length )
はnextInt( i.length )
の範囲の数値を返します。 他のオプションは、同じように動作するMath.Random
を使用しています。
index = (int) Math.floor(Math.random() * i.length);
より良い理解のためには、フォーラム投稿のランダムインターバル(archive.org)をご覧ください 。
java-8では、 ints(int randomNumberOrigin, int randomNumberBound)
のメソッドをRandom
クラスに導入しました。
たとえば、[0、10]の範囲に5つの乱数(または1つ)を生成する場合は、次のようにします。
Random r = new Random();
int[] fiveRandomNumbers = r.ints(5, 0, 11).toArray();
int randomNumber = r.ints(1, 0, 11).findFirst().getAsInt();
最初のパラメータは、生成されたIntStream
のサイズを示します(これは、無制限のIntStream
を生成するオーバーロードされたメソッドです)。
複数の別々の呼び出しを行う必要がある場合は、ストリームから無限プリミティブイテレータを作成できます。
public final class IntRandomNumberGenerator {
private PrimitiveIterator.OfInt randomIterator;
/**
* Initialize a new random number generator that generates
* random numbers in the range [min, max]
* @param min - the min value (inclusive)
* @param max - the max value (inclusive)
*/
public IntRandomNumberGenerator(int min, int max) {
randomIterator = new Random().ints(min, max + 1).iterator();
}
/**
* Returns a random number in the range (min, max)
* @return a random number in the range (min, max)
*/
public int nextInt() {
return randomIterator.nextInt();
}
}
double
値とlong
値についても行うことができます。
それが役に立てば幸い! :)
あなたの最初の解決策のほんの少しの変更で十分でしょう。
Random rand = new Random();
randomNum = minimum + rand.nextInt((maximum - minimum) + 1);
Random
実装の詳細はこちら
ここでは、閉じた[min, max]
範囲から乱数を生成する方法を示す簡単なサンプルを示しますが、 min <= max is true
ホールクラスのフィールドとして再利用することができます。また、すべてのRandom.class
メソッドを1つの場所に持つこともできます
結果の例:
RandomUtils random = new RandomUtils();
random.nextInt(0, 0); // returns 0
random.nextInt(10, 10); // returns 10
random.nextInt(-10, 10); // returns numbers from -10 to 10 (-10, -9....9, 10)
random.nextInt(10, -10); // throws assert
ソース:
import junit.framework.Assert;
import java.util.Random;
public class RandomUtils extends Random {
/**
* @param min generated value. Can't be > then max
* @param max generated value
* @return values in closed range [min, max].
*/
public int nextInt(int min, int max) {
Assert.assertFalse("min can't be > then max; values:[" + min + ", " + max + "]", min > max);
if (min == max) {
return max;
}
return nextInt(max - min + 1) + min;
}
}
このアプローチは、 nextInt
アプローチ( https://.com/a/738651/360211よりも偏っており効率が低いことに注意してhttps://.com/a/738651/360211
これを達成するための1つの標準パターンは次のとおりです。
Min + (int)(Math.random() * ((Max - Min) + 1))
Java Mathライブラリ関数Math.random()は、 [0,1)
の範囲でdouble値を生成します。 この範囲には1が含まれていないことに注意してください。
最初に特定の範囲の値を取得するには、対象とする値の範囲の大きさを掛ける必要があります。
Math.random() * ( Max - Min )
これは[0,Max-Min)
の範囲の値を返します。ここで 'Max-Min'は含まれません。
たとえば、 [5,10)
が必要な場合は、5つの整数値をカバーする必要があります
Math.random() * 5
これは[0,5)
の範囲の値を返します。ここでは5は含まれません。
今度は、この範囲をあなたが目標とする範囲にシフトする必要があります。 これを行うには、最小値を追加します。
Min + (Math.random() * (Max - Min))
[Min,Max)
の範囲の値が得られます。 私たちの例に従えば、それは[5,10)
を意味します:
5 + (Math.random() * (10 - 5))
しかし、これはまだMax
を含んでおらず、あなたは二重価値を得ています。 Max
値を取得するには、範囲パラメータ(Max - Min)
1を加え、intにキャストして小数部分を切り捨てる必要があります。 これは次の方法で達成されます。
Min + (int)(Math.random() * ((Max - Min) + 1))
そしてそこにあなたはそれを持っています。 [Min,Max]
、または例[5,10]
の範囲のランダムな整数値です。
5 + (int)(Math.random() * ((10 - 5) + 1))
ただRandomクラスを使用してください:
Random ran = new Random();
// Assumes max and min are non-negative.
int randomInt = min + ran.nextInt(max - min + 1);
つかいます:
Random ran = new Random();
int x = ran.nextInt(6) + 5;
整数x
は現在、 5-10
結果が得られる乱数になります。
もう一つの選択肢はApache Commonsを使うことです:
import org.apache.commons.math.random.RandomData;
import org.apache.commons.math.random.RandomDataImpl;
public void method() {
RandomData randomData = new RandomDataImpl();
int number = randomData.nextInt(5, 10);
// ...
}
インクルーシブ/排他的な範囲の任意の組み合わせで範囲内のランダムなints
を生成するのに役立つクラスは次のとおりです。
import java.util.Random;
public class RandomRange extends Random {
public int nextIncInc(int min, int max) {
return nextInt(max - min + 1) + min;
}
public int nextExcInc(int min, int max) {
return nextInt(max - min) + 1 + min;
}
public int nextExcExc(int min, int max) {
return nextInt(max - min - 1) + 1 + min;
}
public int nextIncExc(int min, int max) {
return nextInt(max - min) + min;
}
}
マルチスレッド環境の場合はjava.util.Randomクラスに相当するThreadLocalRandom 乱数の生成は、各スレッドでローカルに実行されます。 だから私たちは競合を減らしてより良いパフォーマンスを得ています。
int rand = ThreadLocalRandom.current().nextInt(x,y);
x、y - 間隔(例えば、1,10)
ランダムではなくSecureRandomを使用する方が良いでしょう。
public static int generateRandomInteger(int min, int max) {
SecureRandom rand = new SecureRandom();
rand.setSeed(new Date().getTime());
int randomNum = rand.nextInt((max - min) + 1) + min;
return randomNum;
}
乱数が必要な場合は、APIのRandomクラスはお勧めしません。 それはあまりにも小さな期間を持っています。 代わりにメルセンヌ・トゥイスターをお試しください。 Javaの実装があります 。
例を挙げてみましょう。
5-10の間の数値を生成したいとします。
int max = 10;
int min = 5;
int diff = max - min;
Random rn = new Random();
int i = rn.nextInt(diff + 1);
i += min;
System.out.print("The Random Number is " + i);
これを理解してみましょう ...
最高値でminを初期化し、最低値でminを初期化します。
さて、得られる可能な値の数を決定する必要があります。 この例では、次のようになります。
5,6,7,8,9,10
したがって、この数は最大 - 最小+1になります。
すなわち10 -5 + 1 = 6
乱数は0〜5の間の数値を生成します。
すなわち、0,1,2,3,4,5
乱数に最小値を加えると次のようになります:
5,6,7,8,9,10
したがって、我々は所望の範囲を得る。
私はこの例を見つけた乱数を生成する :
この例では、特定の範囲にランダムな整数を生成します。
import java.util.Random;
/** Generate random integers in a certain range. */
public final class RandomRange {
public static final void main(String... aArgs){
log("Generating random integers in the range 1..10.");
int START = 1;
int END = 10;
Random random = new Random();
for (int idx = 1; idx <= 10; ++idx){
showRandomInteger(START, END, random);
}
log("Done.");
}
private static void showRandomInteger(int aStart, int aEnd, Random aRandom){
if ( aStart > aEnd ) {
throw new IllegalArgumentException("Start cannot exceed End.");
}
//get the range, casting to long to avoid overflow problems
long range = (long)aEnd - (long)aStart + 1;
// compute a fraction of the range, 0 <= frac < range
long fraction = (long)(range * aRandom.nextDouble());
int randomNumber = (int)(fraction + aStart);
log("Generated : " + randomNumber);
}
private static void log(String aMessage){
System.out.println(aMessage);
}
}
このクラスの実行例:
Generating random integers in the range 1..10.
Generated : 9
Generated : 3
Generated : 3
Generated : 9
Generated : 4
Generated : 1
Generated : 3
Generated : 9
Generated : 10
Generated : 10
Done.
rand.nextInt((max+1) - min) + min;
private static Random random = new Random();
public static int getRandomInt(int min, int max){
return random.nextInt(max - min + 1) + min;
}
または
public static int getRandomInt(Random random, int min, int max)
{
return random.nextInt(max - min + 1) + min;
}
public static Random RANDOM = new Random(System.nanoTime());
public static final float random(final float pMin, final float pMax) {
return pMin + RANDOM.nextFloat() * (pMax - pMin);
}