12

I need some help with percent chance in C# code. Let's say i have for loop from 1 to 100 and in that loop i have an "if" code that i want to be executed 70% times (on random). How would i achieve that? So something like this:

static void Main(string[] args)
{
    var clickPercentage = 70;

    for (int i = 0; i < 100; i++)
    {
        if (chance)
        {
            //do 70% times
        }
    }
}

So for top example i would want if code to be hit with a chance of 70%, about 70 times for my example.

Things i tried: (nowhere near 70%, more like 1 or 2% chance)

static void Main(string[] args)
{
    var clickPercentage = 70;

    for (int i = 0; i < 100; i++)
    {
        var a = GetRadnomNumber(1, clickPercentage);
        var b = GetRadnomNumber(1, 101);

        if (a <= b)
        {
            Console.WriteLine($"Iteracija {i} - {b} <= {a}");
        }
    }
}

public static int GetRadnomNumber(int min, int max)
{
    var random = new Random();
    var retVal = random.Next(min, max);

    return retVal;
}
M. Schena
  • 2,039
  • 1
  • 21
  • 29
azza idz
  • 623
  • 3
  • 13
  • 27
  • 1
    Borderline dupe. You ***really*** need to read this: http://stackoverflow.com/questions/767999/random-number-generator-only-generating-one-random-number – spender Jun 16 '16 at 12:00
  • 1
    I suggest changing your method from `GetRadnomNumber` to `GetRandomNumber` – Jamie Rees Jun 16 '16 at 12:10
  • Possible duplicate of [Random number generator only generating one random number](https://stackoverflow.com/questions/767999/random-number-generator-only-generating-one-random-number) – Jim G. Dec 26 '18 at 13:57

4 Answers4

10

Use the Random class.

You can use Random.Next(100) to get a random int between 0 and 99:

public static Random RandomGen = new Random();
.....

int clickPercentage = 70;
for (int i = 0; i < 100; i++)
{
    int randomValueBetween0And99 = RandomGen.Next(100);
    if (randomValueBetween0And99 < clickPercentage)
    {
        //do 70% times
    }
}

It's important that you don't create the random instance in the loop because it's default constructor uses the current time as seed. That could cause repeating values in the loop. That's why i've used a static field. You could also pass a Random instance to a method to ensure that the caller is responsible for the lifetime and the seed. Sometimes it's important to use the same seed, for example to repeat the same test.

Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
4

Wrapping it up as a function:

private static Random generator = null; 

/*
 *  Calls onSuccess() chanceOfSuccess% of the time, otherwise calls onFailure() 
 */
public void SplitAtRandom(int chanceOfSuccess, Action onSuccess, Action onFailure)
{
    // Seed
    if (generator == null)
        generator = new Random(DateTime.Now.Millisecond);

    // By chance
    if (generator.Next(100) < chanceOfSuccess)
    {
        if (onSuccess != null)
            onSuccess();
    }
    else
    {
        if (onFailure != null)
            onFailure();
    }
}

and to use it:

for (int i = 0; i < 100; i++)
{
    SplitAtRandom(70, 
                  () => { /* 70% of the time */ }, 
                  () => { /* 30% of the time */ });
} 
2

Not too sure about your logic, but from a quick glance you are creating a random object in a loop.

The problem with this is that the Random class uses current time as a seed. If the seed is the same, the Random class will produce the same sequence of random numbers. As the CPUs these days are really fast, it usually happens that several loop iterations will have the exact same seed, and hence, the output of the random number generator will be completely predictable (and the same as the previous ones).

To avoid this, only create an instance of a Random class once and reuse it in your code, something like

private static readonly Random _rnd = new Random();
// use _rnd in you code and don't create any other new Random() instances
oleksii
  • 35,458
  • 16
  • 93
  • 163
  • Was just reading about random instances, and yes i did have a lot of same "random" numbers didn't realize that was problem. – azza idz Jun 16 '16 at 12:07
0

Basically you don´t need a new Random-instance every iteration. Simple use this:

var r = new Random();

for(int i = 0; i < 100; i++)
{
    var p = r.Next(100);
    if (p >= 1 - myThreshhold) // do anything in 70% of cases
}

Alternatively you can also use if (p <= myThreshold).

MakePeaceGreatAgain
  • 35,491
  • 6
  • 60
  • 111