我想在x和y之间生成随机延迟。我希望输出比x或y更常见于x和y的中间。
例如,如果我的x为10且y为20,我希望最常见的输出为15。
我一直试图在纸上解决这个问题但不幸的是,我不是数学天才。
我尝试了一些使用Random.nextGuassian()的公式,但我根本无法理解它给出的奇数输出。
答案 0 :(得分:0)
Java Random.nextGaussian()
返回以均值为零为中心的值。如果希望值以15为中心,则将{15}添加到Random.nextGaussian()
返回的值。更一般地说,如果您希望值位于x
和y
之间的中间位置,请执行以下操作:
delay = Random.nextGaussian + ( (x + y) * 0.5 );
在正态分布中,99.7%的数据样本位于平均值之上和之下的3个标准差内。 Random.nextGaussian()
生成标准差为1.0的值,因此如果平均值为15,那么它返回的值的99.7%将介于12和18之间。但是,它偶尔会返回小于x
的值或大于y
,因此您需要检查这些情况。简单地强制值小于x
到x
且大于y
到y
的值可能足以满足您的使用案例:
if (delay < x) {
delay = x;
} else if (delay > y) {
delay = y;
}
参考文献:
答案 1 :(得分:0)
在实现具有抛物线分布的随机数生成器之前,您需要定义您的意思。这是一次尝试:
分布在区间0到1上定义为二次多项式。在此间隔内,曲线下方的区域必须为1.通过改变参数 K 和 M ,您可以调整分布。 K 确定抛物线中心在区间中的位置, M 决定“拉”抛物线的距离。在您的问题中, K 是½,因为您希望顶点位于间隔的中间。您没有指定 M 。
抛物线由函数
指定f ( x )= ax 2 + bx + C 的
提供 K 和 M 并且0到1区间曲线下方的区域应为1,您需要计算 a , b 和 c 。
如果 K =½且 M =½,那么确切的解决方案是
f ( x )= 6 x 2 - 6 x + 2。
如果此解决方案不充分(因为您需要 K 和/或 M 的其他值),则必须创建一组方程式。基于如何放置抛物线,已知 a 必须为正, b 为负且 c &gt; 中号
抛物线的顶点应触及( K , M )。这意味着 f ( K )= M 或 f ( K ) - M = 0。
为了使顶点触及这一点,修正的二次方程的判别式必须为0:
d' = b 2 - 4 a ( c - < EM>中号)
如果您知道 a 和 c ,则可以计算 b (已知 b 已经 b 否定创造所需的抛物线):
b =-√(4 a ( c - M ))[等式A]
顶点的等式是:
f ( K ) - M = aK 2 + bK + c - M = 0 [等式B]
抛物线下面的区域是根据 f ( x )的间隔0到1的定积分计算的
∫ 0 1 f ( x ) dx = a / 3 + b / 2 + c = 1 [等式C]
您可以将等式A中的 b 替换为等式B和C,给出两个具有两个未知数 a 和 c 的等式。不幸的是,这些方程是非线性的,我的数学生锈了所以我选择了“简单路径”并使用Excel中的Solver插件来查找 K 和中号。如果你采用这种方法,你应该在求解器中添加一个 d'不能为负的约束以及对 a 和 c 的约束如上所述。
现在您知道 a , b 和 c 所需的抛物线方程式,创建具有抛物线分布的随机数的方法是如下:
这个挑选的解决方案是一个抛物线分布的随机数。
f ( x )的倒数是
x =( - b ±√( b 2 - 4 a ( c - y )))/ 2 a
结合所有这些我创建了一个C#类。您必须为参数 K , M , a , b 和替换所需的值ç的。或者您可以扩展此代码以从 K 和 M <来计算 a , b 和 c em>使用数值算法。
class ParabolicRandom
{
const double k = 0.5D;
const double m = 0.5D;
const double a = 6;
const double b = -6;
const double c = 2;
readonly double yMin = m;
readonly double yMax = Math.Max(F(0D), F(1D));
Random random;
public ParabolicRandom() => random = new Random();
public ParabolicRandom(int seed) => random = new Random(seed);
public double Next()
{
var randomY = (yMax - yMin) * random.NextDouble() + yMin;
var randomX1 = ReverseF1(randomY);
var randomX2 = ReverseF2(randomY);
if (randomX1 < 0D || randomX1 > 1D)
return randomX2;
if (randomX2 < 0D || randomX2 > 1D)
return randomX1;
return random.Next()%2 == 0 ? randomX1 : randomX2;
}
static double F(double x) => a * x * x + b * x + c;
double ReverseF1(double y) => (-b + Math.Sqrt(b * b - 4 * a * (c - y))) / (2 * a);
double ReverseF2(double y) => (-b - Math.Sqrt(b * b - 4 * a * (c - y))) / (2 * a);
}
要生成10到20之间的随机数,15的一半,而10和20,你可以像这样使用它:
var lowerInclusive = 10;
var upperInclusive = 20;
var value = (int) Math.Floor(
(upperInclusive - lowerInclusive + 1)*parabolicRandom.Next() + lowerInclusive);