web-dev-qa-db-ja.com

Java:0 <= x <nの範囲のランダムな長い数値

Randomクラスには、指定された範囲でランダムなintを生成するメソッドがあります。例えば:

Random r = new Random(); 
int x = r.nextInt(100);

これにより、0以上100未満の整数が生成されます。長い数値でもまったく同じようにしたいと思います。

long y = magicRandomLongGenerator(100);

ランダムクラスにはnextLong()のみがありますが、範囲を設定することはできません。

121

Java 7(またはAndroid AP​​I Level 21 = 5.0+)以降では、ThreadLocalRandom.current().nextLong(n)を直接使用できます(0≤x <nの場合) )およびThreadLocalRandom.current().nextLong(m, n)(m≤x <nの場合)。詳細については、 @ Alex の回答を参照してください。


Java 6(またはAndroid 4.x)にこだわっている場合は、外部ライブラリを使用する必要があります(たとえばorg.Apache.commons.math3.random.RandomDataGenerator.getRandomGenerator().nextLong(0, n-1)、参照 @ mawaldne 's answer)、または独自のnextLong(n)を実装します。

http://Java.Sun.com/j2se/1.5.0/docs/api/Java/util/Random.htmlnextIntに従って

 public int nextInt(int n) {
     if (n<=0)
                throw new IllegalArgumentException("n must be positive");

     if ((n & -n) == n)  // i.e., n is a power of 2
         return (int)((n * (long)next(31)) >> 31);

     int bits, val;
     do {
         bits = next(31);
         val = bits % n;
     } while(bits - val + (n-1) < 0);
     return val;
 }

したがって、nextLongを実行するようにこれを変更できます。

long nextLong(Random rng, long n) {
   // error checking and 2^x checking removed for simplicity.
   long bits, val;
   do {
      bits = (rng.nextLong() << 1) >>> 1;
      val = bits % n;
   } while (bits-val+(n-1) < 0L);
   return val;
}
140
kennytm

範囲内で(ユーティリティメソッドを使用せずに)数値を生成する標準的な方法は、範囲でdoubleを使用することです。

long range = 1234567L;
Random r = new Random()
long number = (long)(r.nextDouble()*range);

0(包括的)と範囲(排他的)の間のlongを与えます。同様に、xとyの間の数値が必要な場合:

long x = 1234567L;
long y = 23456789L;
Random r = new Random()
long number = x+((long)(r.nextDouble()*(y-x)));

1234567(包括的)から123456789(包括的)までの長さを提供します

注:longへのキャストは乗算よりも優先順位が高いため、括弧を確認してください。

72
M. Jessup

ThreadLocalRandom

ThreadLocalRandom には nextLong(long bound) メソッドがあります。

long v = ThreadLocalRandom.current().nextLong(100);

また、0以外のOriginが必要な場合は、 nextLong(long Origin, long bound) があります。Origin(包括的)とバウンド(排他的)を渡します。

long v = ThreadLocalRandom.current().nextLong(10,100); // For 2-digit integers, 10-99 inclusive.

SplittableRandom には同じnextLongメソッドがあり、再現可能な数列が必要な場合はシードを選択できます。

65
Alex

上記の方法は非常に効果的です。 Apache commons(org.Apache.commons.math.random)を使用している場合は、RandomDataを確認してください。メソッドがあります:nextLong(long lower、long upper)

http://commons.Apache.org/math/userguide/random.html

http://commons.Apache.org/math/api-1.1/org/Apache/commons/math/random/RandomData.html#nextLong(long、%20long)

12
mawaldne

「%」演算子を使用します

resultingNumber = (r.nextLong() % (maximum - minimum)) + minimum;

「%」演算子を使用することにより、最大値で割ったときの残りを取得します。これにより、0(包括的)から除数(排他的)までの数字のみが残ります。

例えば:

public long randLong(long min, long max) {
    return (new Java.util.Random().nextLong() % (max - min)) + min;
}
11
Septic Overflow

この投稿をありがとうございます。それはまさに私が必要としたものです。私が働いていた部分を得るために何かを変更する必要がありました。

私は次のものを入手しました(上記に含まれています):

long number = x+((long)r.nextDouble()*(y-x));

次のように変更して動作します。

long number = x+ (long)(r.nextDouble()*(y-x));

(long)r.nextDouble()は常にゼロであるためです。

2
Cece

FromJava 8API

API dochttps://docs.Oracle.com/javase/8/docs/apiから実際の実装を取得する方が簡単かもしれません/Java/util/Random.html#longs-long-long-long- longsストリームの生成に使用しています。そして、あなたのOriginは質問のように「0」にすることができます。

long nextLong(long Origin, long bound) {
  long r = nextLong();
  long n = bound - Origin, m = n - 1;
  if ((n & m) == 0L)  // power of two
    r = (r & m) + Origin;
  else if (n > 0L) {  // reject over-represented candidates
    for (long u = r >>> 1;            // ensure nonnegative
         u + m - (r = u % n) < 0L;    // rejection check
         u = nextLong() >>> 1) // retry
        ;
    r += Origin;
  }
  else {              // range not representable as long
    while (r < Origin || r >= bound)
      r = nextLong();
  }
  return r;
}
2
Vitaliy

[0、m)の範囲で一様に分布した擬似乱数が必要な場合は、以下に示すように、モジュロ演算子とnextLong()メソッドと組み合わせた絶対値メソッドを使用してみてください。

Math.abs(Rand.nextLong()) % m;

Randはランダムオブジェクトです。

モジュロ演算子は、2つの数値を除算し、それらの数値の残りを出力します。たとえば、3 % 21です。これは、3と2の残りが1であるためです。

nextLong()は[-(2 ^ 48)、2 ^ 48)の範囲(またはその範囲内のどこか)で一様に分布した擬似乱数longを生成するため、その絶対値を取得する必要があります。そうしないと、nextLong()メソッドのモジュロは、[0、m)の範囲外の負の値を返す可能性が50%あります。

最初に要求したのは、[0,100)の範囲の均一に分布した擬似乱数です。次のコードはそうします:

Math.abs(Rand.nextLong()) % 100;
2

Kennytmの答えをさらに改善:Java 8の実際の実装を考慮したサブクラス実装は次のようになります。

public class MyRandom extends Random {
  public long nextLong(long bound) {
    if (bound <= 0) {
      throw new IllegalArgumentException("bound must be positive");
    }

    long r = nextLong() & Long.MAX_VALUE;
    long m = bound - 1L;
    if ((bound & m) == 0) { // i.e., bound is a power of 2
      r = (bound * r) >> (Long.SIZE - 1);
    } else {
      for (long u = r; u - (r = u % bound) + m < 0L; u = nextLong() & Long.MAX_VALUE);
    }
    return r;
  }
}
2
Enrice

ランダム のページから:

メソッドnextLongは、次のようにRandomクラスによって実装されます。

public long nextLong() {
   return ((long)next(32) << 32) + next(32);
}

Randomクラスは48ビットのみのシードを使用するため、このアルゴリズムはすべての可能なlong値を返しません。

したがって、Longを取得したい場合、完全な64ビット範囲を取得することはできません。

範囲が2のべき乗に近い場合、次のように、そのスニペットのようにLongを構築することをお勧めします。

next(32) + ((long)nextInt(8) << 3)

たとえば、35ビットの範囲を取得します。

1
Phil

以下のメソッドは、10000000000〜9999999999の値を返します。

long min = 1000000000L
long max = 9999999999L    

public static long getRandomNumber(long min, long max){

    Random random = new Random();         
    return random.nextLong() % (max - min) + max;

}
1
Arpan Saini

これはどう:

public static long nextLong(@NonNull Random r, long min, long max) {
    if (min > max)
        throw new IllegalArgumentException("min>max");
    if (min == max)
        return min;
    long n = r.nextLong();
    //abs (use instead of Math.abs, which might return min value) :
    n = n == Long.MIN_VALUE ? 0 : n < 0 ? -n : n;
    //limit to range:
    n = n % (max - min);
    return min + n;
}

1

r.nextDouble()を使用するメソッドは以下を使用する必要があります。

long number = (long) (Rand.nextDouble()*max);


long number = x+(((long)r.nextDouble())*(y-x));
0
James David Low
public static long randomLong(long min, long max)
{
    try
    {
        Random  random  = new Random();
        long    result  = min + (long) (random.nextDouble() * (max - min));
        return  result;
    }
    catch (Throwable t) {t.printStackTrace();}
    return 0L;
}
0
XXX