概率相关
2024年12月15日大约 1 分钟
概率相关
/// <summary>
/// 得到随机的bool值
/// </summary>
/// <param name="random"></param>
/// <param name="trueRate">返回true的概率[0, 1]</param>
/// <returns></returns>
public static bool NextBoolean(this System.Random random, double trueRate)
{
return trueRate > random.NextDouble();
}
/// <summary>
/// 产生给定范围的浮点随机数。
/// <paramref name="minValue"/>和<paramref name="maxValue"/>两个参数可自动矫正大小
/// </summary>
/// <remarks> ref: http://stackoverflow.com/questions/5289613/generate-random-float-between-two-floats </remarks>
/// <param name="random"></param>
/// <param name="minValue"></param>
/// <param name="maxValue"></param>
/// <returns></returns>
public static double NextDouble(this System.Random random, double minValue, double maxValue)
{
double min, max;
if (minValue < maxValue)
{
min = minValue;
max = maxValue;
}
else if (minValue > maxValue)
{
min = maxValue;
max = minValue;
}
else
{
return minValue;
}
return min + random.NextDouble() * (max - min);
}
/// <summary>
/// 按照<paramref name="probability"/>的概率加权,获取随机下标。
/// 开闭规则为<c>[,) [,)... [,]</c>,正好在两个概率区间的临界值算作后面区间命中。
/// 概率列表,无须归一化,只有大于0的概率才会被命中。当所有概率都不大于0时,将随机返回一个
/// </summary>
/// <param name="probability"></param>
/// <returns></returns>
public static int NextIndex(this System.Random random, IEnumerable<double> probability)
{
// 概率求和,不考虑负概率
var sum = probability.Aggregate((s, d) => d > 0 ? s + d : s); // 只有大于0的概率才会被命中
if (sum == 0)
return random.Next(probability.Count()); // 当所有概率都不大于0时,将随机返回一个
// 计算随机数
var r = random.NextDouble(0, sum);
// 根据随机数进行区间选取
var i = 0;
foreach (var p in probability)
{
if (p > 0)
{
if (r < p) // 不能用"<="以控制开闭区间
return i;
r -= p;
}
i++;
}
return i;
}