Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

special random number

Tags:

c#

random

numbers

I'd like to have a random number like this:(in C#)

Random r = new Random();
r.next (0,10)

BUT it's important to the random number be more near 8,(or it be usually big), I mean if we use a for:

for (int i =0; i<...;i++)
{
  write: r.next (0,10)
}

the result be like this;

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
like image 858
Vahid.m Avatar asked Jul 31 '09 12:07

Vahid.m


People also ask

Why is 17 the most common random number?

Seventeen is: Described at MIT as 'the least random number', according to the Jargon File. This is supposedly because in a study where respondents were asked to choose a random number from 1 to 20, 17 was the most common choice. This study has been repeated a number of times.

What is the most random number ever?

The short answer is that 17 is the most random number.


1 Answers

You need to weight your results. You can do that with something like this:

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)];
}

If I knew my range was small and consistent, I'd use the table - it's trivial to make it its own class.

For completeness, I'll also add this class in. This class borrows from image processing and uses the gamma correction function: a value between 0 and 1 raised to gamma, which returns a value between 0 and 1 but distributed more to the low end if gamma < 1.0 and more to the high end if 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;
    }
}

(from comments, moved r out of GetWeightedRandom(). Also added range checking to Next())

OK, let's really go to town here. I'm channeling John skeet for this - it's an abstract class with a template property that returns a transform function that maps the range [0..1) to [0..1) and scales the random number to that range. I also reimplemented gamma in terms of it and implemented sin and cos as well.

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); }
    }
}
like image 148
plinth Avatar answered Nov 08 '22 14:11

plinth