特殊随机数

Vah*_*d.m 7 c# random numbers

我想要一个这样的随机数:(在C#中)

Random r = new Random();
r.next (0,10)
Run Code Online (Sandbox Code Playgroud)

但重要的是随机数更接近8,(或通常很大),我的意思是如果我们使用a:

for (int i =0; i<...;i++)
{
  write: r.next (0,10)
}
Run Code Online (Sandbox Code Playgroud)

结果是这样的;

8 7 6 9 1 0 5 3 2
2 3 8 9 7 7 6 2 3
8 8 9 7 2 8 2 8 4
3
Run Code Online (Sandbox Code Playgroud)

pli*_*nth 29

你需要加权你的结果.你可以这样做:

private int[] _distribution = new int[] { 0, 1, 2, 3, 4, 5, 6, 6, 7, 7, 8, 8, 8, 9, 9 };
Random _r = new Random();

public int GetWeightedRandom()
{
    return _distribution[_r.Next(0, _distribution.Length)];
}
Run Code Online (Sandbox Code Playgroud)

如果我知道我的范围很小并且一致,我会使用这个表 - 将它变成自己的类是微不足道的.

为了完整起见,我还要添加这个类.这个类借用了图像处理并使用了伽马校正函数:0到1之间的值被提升到gamma,它返回一个介于0和1之间的值,但更多地分配到低端如果gamma> 1.0,则gamma <1.0,如果gamma> 1.0则更高.

public class GammaRandom {
    double _gamma;
    Random _r;

    public GammaRandom(double gamma) {
        if (gamma <= 0) throw new ArgumentOutOfRangeException("gamma");
        _gamma = gamma;
        _r = new Random();
    }
    public int Next(int low, int high) {
       if (high <= low) throw new ArgumentOutOfRangeException("high");
       double rand = _r.NextDouble();
       rand = math.Pow(rand, _gamma);
       return (int)((high - low) * rand) + low;
    }
}
Run Code Online (Sandbox Code Playgroud)

(来自评论,将r移出GetWeightedRandom().还将范围检查添加到Next())

好的,我们真的去这里的小镇.我正在为此引导John双向飞碟 - 这是一个带有模板属性的抽象类,它返回一个将范围[0..1]映射到[0..1]的变换函数,并将随机数缩放到该范围.我也根据它重新实现了伽玛,并实现了sin和cos.

public abstract class DelegatedRandom
{
    private Random _r = new Random();
    public int Next(int low, int high)
    {
        if (high >= low)
            throw new ArgumentOutOfRangeException("high");
        double rand = _r.NextDouble();
        rand = Transform(rand);
        if (rand >= 1.0 || rand < 0) throw new Exception("internal error - expected transform to be between 0 and 1");
        return (int)((high - low) * rand) + low;
    }
    protected abstract Func<double, double> Transform { get; }
}

public class SinRandom : DelegatedRandom
{
    private static double pihalf = Math.PI / 2;
    protected override Func<double, double> Transform
    {
        get { return r => Math.Sin(r * pihalf); }
    }
}
public class CosRandom : DelegatedRandom
{
    private static double pihalf = Math.PI / 2;
    protected override Func<double, double> Transform
    {
        get { return r => Math.Cos(r * pihalf); }
    }
}
public class GammaRandom : DelegatedRandom
{
    private double _gamma;
    public GammaRandom(double gamma)
    {
        if (gamma <= 0) throw new ArgumentOutOfRangeException("gamma");
        _gamma = gamma;
    }
    protected override Func<double, double> Transform
    {
        get { return r => Math.Pow(r, _gamma); }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 我还建议将r = new Random()声明移出方法,因为dot net有一个习惯,就是我们对新实例化的随机对象的预期不那么随机. (4认同)
  • 这对于相对较小的数字来说很好,但是如果你想要一个以1000000为中心的分布,你需要一个非常大的数组......我认为使用分布函数会更好. (3认同)

Tho*_*que 2

您需要一个分布函数,它接受 0 到 1 之间的数字并将其转换为您想要的范围内的数字,并对特定数字赋予更高的权重。您可以使用三角函数(sin、cos、...)、指数函数或多项式创建这样的函数。

更新:查看此页面以获取有关概率分布的更多信息

  • 多项式是一个代数函数,其形式为: f(x) = an*x^n + (an-1)*x^(x-1) + ... a2*x^2 + a1*x + a0 ; (3认同)