在Java中生成特定范围内的随机双精度数

11

我看到过一些解释这个问题的帖子,但它们都使用整数值,而且我并不完全理解,所以提出这个问题:

我正在尝试在 Java 中生成范围为 (-1554900.101) 到 (52952058699.3098) 的随机数,我想知道是否有人能够解释一下这个问题,因为我真的想理解它。

我的想法: 这样做是否正确? 1)在指定范围内生成一个随机整数 2)将生成的数字除以π以获得浮点/双精度随机结果

先谢谢了。


1
我真的很想知道那些精确限制背后的原因 :) - adelphus
在Java 7中,这里有一个更简单的答案:https://dev59.com/pHA65IYBdhLWcg3wsg2A#32808589。 - Tunaki
5个回答

38

这是个想法。假设你需要获取一个随机数在某一个范围内,比如说 [-1.1,2.2]。首先让我们以简单的例子开始。该范围长度为3.3,因为2.2 - (-1.1) = 3.3。现在,大多数“随机”函数会返回一个在区间[0,1)内的数字,其长度为1,因此我们需要将该随机数进行缩放,使其适应我们所需的区间。

Random random = new Random();
double rand = random.nextDouble();
double scaled = rand * 3.3;

现在我们的随机数已经具有我们想要的大小,但是我们必须将其在数轴上移动,以使其位于我们想要的确切值之间。 对于这一步,我们只需要将整个范围的下限加到我们缩放后的随机数上,然后就完成了!

double shifted = scaled + (-1.1);

现在我们可以将这些部分组合成一个单独的函数:

protected static Random random = new Random();
public static double randomInRange(double min, double max) {
  double range = max - min;
  double scaled = random.nextDouble() * range;
  double shifted = scaled + min;
  return shifted; // == (rand.nextDouble() * (max-min)) + min;
}

当然,这个函数需要一些错误检查,以处理像NaN这样的意外值,但是这个答案应该说明了一般思路。


如果我使用 Double.MAX_VALUEDouble.MIN_VALUE,你最后一段代码中的第3行不会越界吗? - SOFe
这个答案只对一个值或一系列值正确,但没有考虑使用某些步骤来获取随机值的情况。因此,在获取带有某些步骤的随机序列的情况下,上面的代码即使被循环覆盖了结束点也可能会导致无限循环。 - Sergey V.

7
double lower = -1554900.101;
double upper = 52952058699.3098;
double result = Math.random() * (upper - lower) + lower;

但是 OP 寻求的是一种解释,而不是从 int 类型到 double 类型的转换... - maerics

2
应该是这样的:

它应该类似于:

double rnd = Math.random();

double result = ((long)(rnd * (529520586993098L - (-15549001010L) + 1)) -15549001010L) / 10000.0;
+ 1会平衡范围是[0;1[的事实,因此排除了上限范围。

我们首先尝试找到一个“整数”(真的很长)范围,并且我们加上1来平衡最后一个数字被排除的事实,所以529520586993098L + 15549001010L + 1,然后我们将其乘以rnd,转换为long并减去15549001010L将其移回,最后除以10000.0使其处于正确的“范围”中。

这可能更清晰:

long range = 529520586993098L + 15549001010L + 1;

double temp = rnd * range;
long temp2 = (long)temp;
temp2 -= 15549001010L;

double result = temp2 / 10000.0;

2

这不是我会做的方式。

  • 生成一个随机双精度浮点数。结果在0和1之间。
  • 将此数字乘以(高限制-低限制)(52952058699.3098 - -1554900.101)
  • 添加低限制(随机数+ -1554900.101)

这样,您就得到了低限制和高限制之间的随机数。


1

Random.nextDouble 返回一个范围在 [0, 1[ 的双精度浮点数,因此可以使用它,将其乘以您的范围大小(52952058699.3098 + 1554900.101),然后偏移结果(减去1554900.101)以获得您的数字。

不确定您需要多精确,但是如果没有进行进一步的分析,由于双精度浮点数的处理方式,您可能会得到超出范围的数字。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接