我正在嘗試創建一個隨機浮點生成器(范圍為 0.0-1.0),我可以在其中提供單個目標值和一個強度值,以增加或減少該目標被擊中的機會。例如,如果我的目標是 0.7,并且我有一個高強度值,我希望該函式主要回傳 0.7 左右的值。
換句話說,我想要一個函式,當運行很多次時,會產生這樣的分布圖:
并使用 0.7 作為 mu 將分布移向 0.7。我添加了一個 0.623 的領先系數來將值移動到 0 和 1 之間,并將其從公式遷移到 C#,這可以在下面找到。

用法:
DistributedRandom random = new DistributedRandom();
// roll for the chance to hit
double roll = random.NextDouble();
// add a strength modifier to lower or strengthen the roll based on level or something
double actualRoll = 0.7d * roll;
定義
public class DistributedRandom : Random
{
public double Mean { get; set; } = 0.7d;
private const double limit = 0.623d;
private const double alpha = 0.25d;
private readonly double sqrtOf2Pi;
private readonly double leadingCoefficient;
public DistributedRandom()
{
sqrtOf2Pi = Math.Sqrt(2 * Math.PI);
leadingCoefficient = 1d / (alpha * sqrtOf2Pi);
leadingCoefficient *= limit;
}
public override double NextDouble()
{
double x = base.NextDouble();
double exponent = -0.5d * Math.Pow((x - Mean) / alpha, 2d);
double result = leadingCoefficient * Math.Pow(Math.E,exponent);
return result;
}
}
編輯:如果您不是在尋找類似于您提供的分布直方圖的輸出,而是想要更類似于您繪制的 sigmoid 函式的輸出,我已經創建了一個替代版本。
感謝 Ruzihm 指出這一點。
我繼續使用 CDF 進行正態分布:
其中erf定義為誤差函式:
。我添加了一個系數1.77來縮放輸出以將其保持在 0d - 1d 內。
它應該產生與此類似的數字:

在這里你可以找到替代類:
public class DistributedRandom : Random
{
public double Mean { get; set; } = 0.7d;
private const double xOffset = 1d;
private const double yOffset = 0.88d;
private const double alpha = 0.25d;
private readonly double sqrtOf2Pi = Math.Sqrt(2 * Math.PI);
private readonly double leadingCoefficient;
private const double cdfLimit = 1.77d;
private readonly double sqrt2 = Math.Sqrt(2);
private readonly double sqrtPi = Math.Sqrt(Math.PI);
private readonly double errorFunctionCoefficient;
private readonly double cdfDivisor;
public DistributedRandom()
{
leadingCoefficient = 1d / (alpha * sqrtOf2Pi);
errorFunctionCoefficient = 2d / sqrtPi;
cdfDivisor = alpha * sqrt2;
}
public override double NextDouble()
{
double x = base.NextDouble();
return CDF(x) - yOffset;
}
private double DistributionFunction(double x)
{
double exponent = -0.5d * Math.Pow((x - Mean) / alpha, 2d);
double result = leadingCoefficient * Math.Pow(Math.E, exponent);
return result;
}
private double ErrorFunction(double x)
{
return errorFunctionCoefficient * Math.Pow(Math.E,-Math.Pow(x,2));
}
private double CDF(double x)
{
x = DistributionFunction(x xOffset)/cdfDivisor;
double result = 0.5d * (1 ErrorFunction(x));
return cdfLimit * result;
}
}
uj5u.com熱心網友回復:
我想出了一個可行的解決方案。這并不像我的目標那樣優雅,因為每個結果需要 2 個亂數,但它絕對滿足要求。基本上它需要一個亂數,使用另一個以指數方式向 1 彎曲的亂數,然后向目標移動。
我用 python 寫出來,因為我更容易看到它的直方圖:
import math
import random
# Linearly interpolate between a and b by t.
def lerp(a, b, t):
return ((1.0 - t) * a) (t * b)
# What we want the median value to be.
target = 0.7
# How often we will hit that median value. (0 = uniform distribution, higher = greater chance of hitting median)
strength = 1.0
values = []
for i in range(0, 1000):
# Start with a base float between 0 and 1.
base = random.random()
# Get another float between 0 and 1, that trends towards 1 with a higher strength value.
adjust = random.random()
adjust = 1.0 - math.pow(1.0 - adjust, strength)
# Lerp the base float towards the target by the adjust amount.
value = lerp(base, target, adjust)
values.append(value)
# Graph histogram
import matplotlib.pyplot as plt
import scipy.special as sps
count, bins, ignored = plt.hist(values, 50, density=True)
plt.show()
目標 = 0.7,強度 = 1

目標 = 0.2,強度 = 1

目標 = 0.7,強度 = 3

目標 = 0.7,強度 = 0
(這意味著均勻分布 - 它可能看起來有點參差不齊,但我測驗過,這只是 python 的亂數生成器。)

轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/385956.html
