生成包含在指定值区间内的随机浮点值的最佳方法是什么?

时间:2016-11-04 21:28:05

标签: java algorithm random floating-point

我想在Java中生成随机浮点值。该值必须在可能值的特定范围内。

例如,我必须生成一个在以下范围内的随机值:

MIN: 41,815080
MAX: 41,829191

这些值恰好代表地图上可能存在的经度范围,但问题更为普遍。

这是一种聪明的方法吗?

4 个答案:

答案 0 :(得分:35)

对于范围内的随机值,公式为:

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);

或者你可以拥有一个更具异国情调的第三方图书馆。

答案 1 :(得分:10)

如果要生成随机浮点值,请尝试:

import java.util.Random;

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

    Random rand = new Random();

    float result = rand.nextFloat() * (max - min) + min;

    return result;

}

希望这会有所帮助。

答案 2 :(得分:1)

代码:

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

答案 3 :(得分:1)

我知道这个问题已有一年多的历史了,但是这里的其他答案都缺少重点。在Java中生成随机浮点值的最佳方法(假设您不需要特定的种子并且不需要cryptographically secure)是ThreadLocalRandom类。

例如,如果您想要一个在其他两个数字之间生成随机数的方法,则可以这样编写:

public static double generateRandomDouble(double min, double max) {
  return ThreadLocalRandom.current().nextDouble(min, max);
}
  • Math.random的问题在于it results in contention。换句话说,如果您的代码与使用Math.random的任何其他代码同时运行,则可能必须重新计算您的随机数。
  • new Random()的问题在于,每次调用它都会创建一个新的Random实例,这是额外的工作,而且更加冗长。
  • 这两种方法的问题在于,它们迫使进行额外的数学运算以将其缩放到所需范围,从而使您的代码可读性更差,更容易出错。 ThreadLocalRandom类有一个非常方便的nextDouble重载,可让您指定“起点”和“界限”,表示最小值和最大值。
  • 这两种方法的另一个问题是它们不精确。因为要进行缩放,所以需要考虑浮点运算固有的舍入问题。实际上,该问题的所有其他答案有时都会产生等于max 的答案。

在上面的代码中,我有两个假设。首先,您希望下限是包含的,上限是排除的。该假设相当微不足道,因为实际降落在边界上的概率非常小。这也是其他答案正在尝试做的事情(尽管它们有时会产生等于max的答案,这与我的答案不同)。我做出的第二个假设是,“随机浮点值”是指浮点值,基于您用标记问题的事实,我假定了该点。因此,我给出了一种返回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;
}

不幸的是,nextFloat上没有ThreadLocalRandom过载,大概是因为他们希望很少有人需要随机的float。若要正确编写此方法,必须纠正浮点舍入问题。因此,我强烈建议您使用产生double的版本。

最后,您应该从不使用Math.random,并且每次需要生成随机数时都不应创建新的Random实例(除非当然,您需要特定的种子)。生成随机数时,默认为ThreadLocalRandom类。

相关问题