生成随机浮动,包括两个边界

时间:2019-05-10 08:32:56

标签: java random

我需要生成[-0.5, 0.5]范围内的随机实数,包括两个边界

我发现了产生相似范围的各种方法,例如

-0.5 + Math.random()

但是上限始终是专有的,我也需要包含在内。 0.5必须在范围内。

6 个答案:

答案 0 :(得分:8)

一种实现此目的的方法是,将随机int创建为-500至500,然后将其除以1000。

int max = 500;
int min = -500;
int randomInt = rand.nextInt((max - min) + 1) + min;
float randomNum = randomInt / 1000.00f;
System.out.println(randomNum);

您可以通过在整数边界和除数中添加和删除零来更改精度。 (例如:创建从-5到+5的整数,然后除以10以降低精度)

该解决方案的一个缺点是它不使用浮点/双精度数据类型提供的最大精度。

答案 1 :(得分:3)

您可以通过比期望的最大值大的最小值( epsilon )来调整上限。要找到ε,请从任意正值开始,并使其尽可能小:

double min = -0.5;
double max = 0.5;

double epsilon = 1;
while (max + epsilon / 2 > max) {
    epsilon /= 2;
}

Random random = ThreadLocalRandom.current();
DoubleStream randomDoubles = random.doubles(min, max + epsilon);

编辑:@DodgyCodeException建议的替代方法(结果与上述相同):

double min = -0.5;
double max = 0.5;

double maxPlusEpsilon = Double.longBitsToDouble(Double.doubleToLongBits(max) + 1L)

Random random = ThreadLocalRandom.current();
DoubleStream randomDoubles = random.doubles(min, maxPlusEpsilon);

答案 2 :(得分:3)

我还没有看到在IEEE-754 Double表示中使用位摆弄的任何答案,所以这是一个。

基于观察到下一个二进制指数的过渡与在二进制表示中添加1相同(实际上这是设计使然):

Double.longBitsToDouble(0x3ff0000000000000L) // 1.0
Double.longBitsToDouble(0x3ffFFFFFFFFFFFFFL) // 1.9999999999999998
Double.longBitsToDouble(0x4000000000000000L) // 2.0

我想到了这个

long   l = ThreadLocalRandom.current().nextLong(0x0010000000000001L);
double r = Double.longBitsToDouble(l + 0x3ff0000000000000L) - 1.5;

此技术仅适用于跨越二进制数(1、2、4、8、0.5、0.25等)的范围,但是对于那些范围,此方法可能是最有效和最准确的方法。本示例的跨度调整为1。对于不跨二进制范围的范围,您仍然可以使用此技术来获得不同的跨度。应用该技术获得[0,1]范围内的数字并将结果缩放到所需的跨度。精度损失可以忽略不计,并且所得的精度实际上与Random.nextDouble(double, double)相同。

对于其他范围,执行以下代码以找到偏移量:

double span = 0.125;

if (!(span > 0.0) || (Double.doubleToLongBits(span) & 0x000FFFFFFFFFFFFFL) != 0)
    throw new IllegalArgumentException("'span' is not a binary number: " + span);
if (span * 2 >= Double.MAX_VALUE)
    throw new IllegalArgumentException("'span' is too large: " + span);

System.out.println("Offset: 0x" + Long.toHexString(Double.doubleToLongBits(span)));

当将此偏移量插入实际代码的第二行时,您将获得[span,2 * span]范围内的值。减去span得到一个从0开始的值。

答案 3 :(得分:1)

给出答案如何回答,这是一个随时可用的功能:

public static double randomFloat(double minInclusive, double maxInclusive, double precision) {
    int max = (int)(maxInclusive/precision);
    int min = (int)(minInclusive/precision);
    Random rand = new Random();
    int randomInt = rand.nextInt((max - min) + 1) + min;
    double randomNum = randomInt * precision;
    return randomNum;
}

然后

System.out.print(randomFloat(-0.5, 0.5, 0.01));

答案 4 :(得分:1)

@OH GOD SPIDERS' answer给了我一个想法,可以将其发展为可以提供更高精确度的答案。当转换为nextLong()时,double给出的值在MIN_VALUE到MAX_VALUE之间,并且具有足够的精度。

double randomNum = (rand.nextLong() / 2.0) / Long.MAX_VALUE;

包含边界的证明:

assert (Long.MIN_VALUE/2.0)/Long.MAX_VALUE == -0.5;
assert (Long.MAX_VALUE/2.0)/Long.MAX_VALUE == 0.5;

答案 5 :(得分:0)

Random.nextDouble给出的值为[0,1]。因此,要将其映射到[-0.5,0.5]的范围,只需减去0.5。

您可以使用此代码获得所需的输出 double value = r.nextDouble() - 0.5;