I need to generate a value in range of truncated normal distribution, for example, in python you could use scipy.stats.truncnorm()
to make
def get_truncated_normal(mean=.0, sd=1., low=.0, upp=10.):
return truncnorm((low - mean) / sd, (upp - mean) / sd, loc=mean, scale=sd)
how it is described here
Is there any package to make something in go or should I write the following function myself?
I tried following, how the doc says, but it makes number not in the needed range:
func GenerateTruncatedNormal(mean, sd uint64) float64 {
return rand.NormFloat64() * (float64)(sd + mean)
}
GenerateTruncatedNormal(10, 5)
makes 16.61, -14.54, or even 32.8, but I expect a small chance of getting 15 due to mean = 10
-> 10 + 5 = 15 is maximum value which we can get. What is wrong here? 😅
One way of achieving this consists of
x
from the Normal distribution, with the desired parameters for mean and standard deviation,This respects the Probability Density Function of the Normal distribution, effectively cutting out the left and right tails.
func TruncatedNormal(mean, stdDev, low, high float64) float64 {
if low >= high {
panic("high must be greater than low")
}
for {
x := rand.NormFloat64()*stdDev + mean
if low <= x && x < high {
return x
}
// fmt.Println("missed!", x)
}
}
If the [low..high] interval is very narrow, then it will take a bit more computation time, as more generated numbers will be thrown away. However, it still converges very fast in practice.
I checked the code above by plotting its results against and compare them to the results of scipy's truncnorm, and they do produce equivalent charts.