Java 以标准偏差生成特定范围内的随机数?

Java 以标准偏差生成特定范围内的随机数?,java,random,Java,Random,我已经知道如何在一定范围内生成随机数。我可以通过使用 rand.nextInt((max - min) + 1) + min; 问题是,我还想为这些数字设置一个标准偏差。数字也必须是正数,并且不在0和1之间 编辑我删除了ThreadLocalRandom类,因为我无法在该类中设置种子,并且这些随机数应该可以在不同的系统中复制。选择标准偏差(或方差)对于有界分布,只能根据取决于所选分布和间隔的边界(最小值,最大值)的约束来执行。某些分布可能允许您将方差设置为任意小(例如),而其他分布(如)在设置

我已经知道如何在一定范围内生成随机数。我可以通过使用

rand.nextInt((max - min) + 1) + min;
问题是,我还想为这些数字设置一个标准偏差。数字也必须是正数,并且不在0和1之间


编辑我删除了ThreadLocalRandom类,因为我无法在该类中设置种子,并且这些随机数应该可以在不同的系统中复制。

选择标准偏差(或方差)对于有界分布,只能根据取决于所选分布和间隔的边界
(最小值,最大值)
的约束来执行。某些分布可能允许您将方差设置为任意小(例如),而其他分布(如)在设置边界
(min,max)
后不允许任何灵活性。在任何情况下,都无法使方差任意大——边界确实阻止了这一点(它们总是输入分布方差的表达式)

我将用一个非常简单的例子来说明这一点,这个例子可以在不需要任何第三方库的情况下实现。让我们假设在区间<代码>(min,max)< /代码>的对称分布上,对称性意味着分布的平均e(x)位于区间的中间:<代码> e(x)=(min +max)/2 < /代码> .<
使用Random的
nextDouble
x=a+(b-a)*rnd.nextDouble()
将在区间
a中为您提供均匀分布的随机变量这有帮助吗@statboy您必须指定您想要的分发类型。您的
nextInt
示例生成的变量(StdDev)已经由
min
max
参数确定(请参见wikipedia链接)。在您最近的编辑中,我删除了我的答案,因为它显然没有满足您编辑的要求(事后)数字也必须是正数,并且不在0和1之间。您需要进一步说明这些限制下的“标准偏差”的含义。@StefanZobel a scaled&translated提供了很大的灵活性。@StefanZobel如果OP希望将Beta版迁移到1到
c
之间,请按
c-1
进行缩放,然后添加1。方差受到的影响与您描述的完全相同——加性常数不会改变它,您可以通过
(c-1)^2
(插入符号表示求幂)缩放原始Beta的方差。您能告诉我对称梯形的方差公式是从哪里得到的吗?“我到处都找不到它。”阿波菲斯我用纸和笔手工计算。有趣的是,给出的公式是错误的,尽管它看起来是合理的。也许他们只是交换了变量。更糟糕的是,甚至
E(X)
都不正确。我找不到一个使用
(a,b,c,d)
表示法的正确方程式,所以我不得不自己推导出来。
/**
 * Variance of a symmetric trapezoidal distribution with parameters
 * {@code a < b < c < d} and the length of {@code d - c = b - a}
 * (by symmetry) identified by {@code x}.
 * 
 * @param a support lower bound
 * @param d support upper bound
 * @param x length of {@code d - c = b - a}, constrained to lie in the open
 *          interval {@code (0, (d-a)/2)}
 * @return variance of the symmetric trapezoidal distribution defined by
 *         the triple {@code (a, d, x)}
 */
static double varSymTrapezoid(double a, double d, double x) {
    if (a <= 0.0 || d <= 0.0 || a >= d) {
        throw new IllegalArgumentException();
    }
    if (x <= 0.0 || x >= (d - a) / 2) {
        throw new IllegalArgumentException();
    }
    double b = a + x;
    double c = d - x;
    double b3 = pow(b, 3);
    double c3 = pow(c, 3);
    double ex2p1 = pow(b, 4) / 4 - a * b3 / 3 + pow(a, 4) / 12;
    double ex2p2 = (c3 / 3 - b3 / 3) * (d - c);
    double ex2p3 = pow(c, 4) / 4 - d * c3 / 3 + pow(d, 4) / 12;
    double ex2 = (ex2p1 + ex2p2 + ex2p3) / ((d - b) * (d - c));
    return ex2 - pow((a + d) / 2, 2);
}
/**
 * Find the displacement {@code x} for the given {@code stddev} by simple
 * bisection.
 * @param min support lower bound
 * @param max support upper bound
 * @param stddev the standard deviation we want
 * @return the length {@code x} of {@code d - c = b - a} that yields a
 * standard deviation roughly equal to {@code stddev}
 */
static double bisect(double min, double max, double stddev) {
    final double eps = 1e-4;
    final double var = pow(stddev, 2);
    int iters = 0;
    double a = eps;
    double b = (max - min) / 2 - eps;
    double x = eps;
    double dx = b - a;

    while (abs(dx) > eps && iters < 150 && eval(min, max, x, var) != 0.0) {
        x = ((a + b) / 2);
        if ((eval(min, max, a, var) * eval(min, max, x, var)) < 0.0) {
            b = x;
            dx = b - a;
        } else {
            a = x;
            dx = b - a;
        }
        iters++;
    }
    if (abs(eval(min, max, x, var)) > eps) {
        throw new RuntimeException("failed to find solution");
    }
    return x;
}

/**
 * Function whose root we want to find.
 */
static double eval(double min, double max, double x, double var) {
    return varSymTrapezoid(min, max, x) - var;
}
/**
 * Return a pseudorandom double for the symmetric trapezoidal distribution
 * defined by the triple {@code (min, max, x)}
 * @param min support lower bound
 * @param max support upper bound
 * @param x length of {@code max - c = b - min}, constrained to lie in the
 *          open interval {@code (0, (max-min)/2)}
 */
public static double symTrapezoidRandom(double min, double max, double x) {
    final double a1 = 0.5 * min;
    final double a2 = a1;

    final double b1 = max - a2 - x;
    final double b2 = a2 + x;

    if ((a1 + b2) >= (a2 + b1)) {
        throw new IllegalArgumentException();
    }

    double u = a1 + (b1 - a1) * rnd.nextDouble();
    double v = a2 + (b2 - a2) * rnd.nextDouble();
    return u + v;
}