web-dev-qa-db-ja.com

指定された値の間隔に含まれるランダムなフロート値を生成する最良の方法は何ですか?

Javaでランダムな浮動小数点値を生成したい。値は、可能な値の特定の範囲内にある必要があります。

たとえば、次の範囲のランダムな値を生成する必要があります。

MIN: 41,815080
MAX: 41,829191

これらの値はたまたま地図上の可能な経度の範囲を表していますが、より一般的には問題が当てはまります。

それを行うスマートな方法は何ですか?

15
AndreaNobili

範囲内のランダムな値の場合、式は次のとおりです。

_double random = min + Math.random() * (max - min);
_

この基本式は、乱数の生成に使用するものに関係なく一定です。

Math.random()は、適度に分散された数値を提供しますが、たとえば任意の乱数ジェネレーターに置き換えることができます(わずかに優れています)。

_Random r = new Random();
double random = min + r.nextDouble() * (max - min);
_

または、本当にfloatが必要な場合:

_float random = min + r.nextFloat() * (max - min);
_

または、よりエキゾチックなサードパーティライブラリを使用できます。

38
Bohemian

ランダムなフロート値を生成したい場合は、これを試してください:

import Java.util.Random;

public static float randFloat(float min, float max) {

    Random Rand = new Random();

    return Rand.nextFloat() * (max - min) + min;

}

これが役に立てば幸いです。

11
Yogesh Darji

コード:

import Java.util.Scanner;


public class Hello 
{

    public static void main(String[] args)
    {       

        Scanner sc=new Scanner(System.in);

        double max,min,randfloat;

        System.out.println("Enter minimum :");
        min=sc.nextDouble();
        System.out.println("Enter maximum :");
        max=sc.nextDouble();    

        randfloat=(Math.random())*(max-min)+min; //Math.random() generates random value between 0 and 1

        System.out.println("Random float value generated is: "+randfloat);
        sc.close();

    }

}

Example

1
Manthan_Admane

この質問は1年以上前のものであることは知っていますが、ここでの他の答えには重要な点が欠けています。 Javaでランダムな浮動小数点値を生成するための最良の方法(特定のシードが不要であり、 cryptographically secure )である必要がないと仮定します。 ThreadLocalRandom クラスです。

たとえば、他の2つの数値の間で乱数を生成するメソッドが必要な場合は、次のように記述できます。

_public static double generateRandomDouble(double min, double max) {
  return ThreadLocalRandom.current().nextDouble(min, max);
}
_
  • _Math.random_の問題は、 競合が発生する であることです。つまり、コードが_Math.random_を使用する他のコードと同時に実行されている場合、乱数を再計算する必要があります。
  • new Random()の問題は、呼び出されるたびに新しいRandomインスタンスを作成することです。これは、余分な作業であり、より冗長です。
  • これらの両方のメソッドの問題は、youを強制的に追加の計算を実行して目的の範囲にスケーリングすることで、コードが読みにくくなり、エラーが発生しやすくなります。 ThreadLocalRandomクラスには、非常に便利な nextDouble オーバーロードがあります。これにより、「Origin」と「bound」、つまり最小と最大を指定できます。
  • これらの方法の両方に関する別の問題は、それらが不正確であることです。スケーリングを行うため、浮動小数点演算に固有の丸めの問題を考慮する必要があります。実際、この質問に対する他のすべての回答は、maxに等しい回答を生成する場合があります。

上記のコードでは、2つの仮定を行っています。まず、下限を包括的にし、上限を排他的にする必要があります。実際に境界に着地する確率は非常に小さいため、この仮定はかなり簡単です。これは、他の回答が実行しようとしていることでもあります(ただし、私の回答とは異なり、最大の回答が作成される場合もあります)。 2番目の仮定は、「ランダムな浮動小数点値」とは、浮動小数点値を意味するということです。これは、質問に floating-point でタグ付けしたという事実に基づいて仮定したものです。したがって、倍精度浮動小数点値であるdoubleを返すメソッドを指定しました。これは、通常Javaで浮動小数点値に使用します。ただし、floatプリミティブを指定する場合は、次の方法を使用できます。

_public static float generateRandomFloat(float min, float max) {
  if (min >= max)
    throw new IllegalArgumentException("max must be greater than min");
  float result = ThreadLocalRandom.current().nextFloat() * (max - min) + min;
  if (result >= max) // correct for rounding
    result = Float.intBitsToFloat(Float.floatToIntBits(max) - 1);
  return result;
}
_

残念ながら、nextFloatThreadLocalRandomオーバーロードはありません。おそらく、ランダムなfloatsを必要とする人はほとんどいないからです。このメソッドを正しく記述するには、浮動小数点の丸めの問題を修正する必要があります。したがって、doubleを生成するバージョンを使用することを強くお勧めします。

結論として、never_Math.random_を使用する必要があり、必要なたびに新しいRandomインスタンスを作成しないでください。乱数を生成するには(もちろん、特定のシードが必要でない限り)。乱数を生成する場合、デフォルトはThreadLocalRandomクラスになります。

1
Finn