Generate random numbers in a certain range with standard deviation?

I already know how to generate random numbers in a range. I can do it using

rand.nextInt((max - min) + 1) + min;

The problem is that I would also like to set the standard deviation for these numbers. The numbers must also be positive, and they are not between 0 and 1

EDIT I removed the ThreadLocalRandom class because I cannot set the seed in this class, and these random numbers must be reproducible on another system.

+4
source share
1 answer

( ) , (min, max) . (, -), (, ) , (min, max). , - ( ).

, - . , (min, max), , E (X) : E(X) = (min + max)/2.

Random nextDouble, x = a + (b - a) * rnd.nextDouble(), a <= x < b, Var(X) = (b - a)^2 / 12 ( , ).

OTH, (a, b), , : Var(X) = (b - a)^2 / 24 ( , , ).

(a < b < c < d) - (a, d). , d - c = b - a, b - a x "" ( , ).

x 0.0 , , (d - a)^2 / 12. x (d - a)/2 , , (d - a)^2 / 24) ( , , ).

, , x, , , , (), (0.2041(d - a), 0.2886(d - a)), , a = min = 2.0 d = max = 10.0, stddevs: (1.6328, 2.3088). , stddev 2.0 (, , ).

3 :

1) , min, max, x

2) - "" , x

3), x, , (min, max, x)

1:

/**
 * 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);
}

, . , 2,5 (varSymTrapezoid(2.0, 10.0, 2.5)), 3.0416, ( 4.0), , 2,5 ( ).

- 4- x, . x , , bisection.

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

bisect 2.0 (bisect(2.0, 10.0, 2.0)) : ~ 1.1716. , x , , , ,

3:

, , X1 ~ U[a1, b1] X2 ~ U[a2, b2] [a1 + a2, b1 + b2] a1 + b2 < a2 + b1 ( 1), a2 + b1 < a1 + b2 ( 2). a2 + b1 = a1 + b2 ( 3), , .

1 (a1 + b2 < a2 + b1). b2 - a2 "" x.

, , , a1, a2, b1 b2 , a1 + a2 = min, b1 + b2 = max, b2 - a2 = x :

/**
 * 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;
}

symTrapezoidRandom(2.0, 10.0, 1.1716) , .

, , , Beta. ( ) , , commons.math.

abs, pow, sqrt java.lang.Math rnd - java.util.Random.

+4

Source: https://habr.com/ru/post/1652462/


All Articles