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

And*_*ili 18 java random algorithm floating-point

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

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

MIN: 41,815080
MAX: 41,829191
Run Code Online (Sandbox Code Playgroud)

这些值恰好代表了地图上一系列可能的经度,但这个问题更为普遍.

什么是聪明的方法呢?

Boh*_*ian 39

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

double random = min + Math.random() * (max - min);
Run Code Online (Sandbox Code Playgroud)

无论您使用什么来生成随机数,这个基本公式都是常量.

Math.random() 提供适度分布均匀的数字,但您可以将其替换为您想要的任何随机数生成器,例如(稍好一些):

Random r = new Random();
double random = min + r.nextDouble() * (max - min);
Run Code Online (Sandbox Code Playgroud)

或者如果你真的想要float:

float random = min + r.nextFloat() * (max - min);
Run Code Online (Sandbox Code Playgroud)

或者你可以有一个更奇特的第三方图书馆.


Yog*_*rji 13

如果要生成随机浮点值,请尝试以下方法:

import java.util.Random;

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

    Random rand = new Random();

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

}
Run Code Online (Sandbox Code Playgroud)

希望这有帮助.

  • 这既不会编译,也无法正常工作。您需要返回一个值,并且返回的值应为`float`类型,而不是`int`类型。 (2认同)

Fin*_*inn 5

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

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

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

在上面的代码中,我做了两个假设。首先,您希望包含的下限和不包含的上限。这个假设相当微不足道,因为实际降落在边界上的概率非常小。这也是其他答案试图做的事情(尽管他们有时会产生等于 max 的答案,这与我的不同)。第二个假设我提出的是,“随机浮点值,”你的意思是一个浮点值,我以为根据你所标记与问题其实。因此,我给出了一个返回 a 的方法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;
}
Run Code Online (Sandbox Code Playgroud)

不幸的是没有nextFloat超载ThreadLocalRandom,大概是因为他们预计很少有人需要 random floats。要正确编写此方法,您必须更正浮点舍入问题。因此,我强烈建议您使用生成double.

总之,您永远不应该使用Math.random,也不应该在Random每次需要生成随机数时都创建一个新实例(当然,除非您需要一个特定的种子)。生成随机数时,默认为ThreadLocalRandom类。