0

I have a function with two arguments say a and b. So basically, whenever I call this method 50% times it should return a and 50% times it should return b.

public string Randomization(string a, string b)

I thought of doing this using random number generation and if number generated is even, return a and if odd, return b. How could I achieve this or is there any other simple way ?

Nisha
  • 3
  • 5
  • Just generate randomly a 0 or a 1 and do an if-else statement. This might help you out: https://stackoverflow.com/questions/1493051/random-number-0-or-1 – Tomsen Dec 05 '20 at 11:42
  • Related: [Fastest way to generate a random boolean](https://stackoverflow.com/questions/19191058/fastest-way-to-generate-a-random-boolean) – Theodor Zoulias Dec 05 '20 at 12:00
  • 50% of times is not gonna help random. Say by your logic if random gives 4 even numbers continuously its 100%a and 0% b. So, if 50% is a hard rule, then you need to keep a counter and /2 to determine it should be a or b. – Ramesh Dec 05 '20 at 12:50
  • 1
    Over how many trials does it need to produce this 50%? And how exact does the percentage need to be. Requiring *precisely* 50% means that the only way to implement that is to just alternate whether it returns `a` or `b`. – Damien_The_Unbeliever Dec 05 '20 at 14:35
  • @Damien_The_Unbeliever No, alternating is not required. You can put `n / 2` of each of `a` and `b` in a list and then shuffle. The resulting sequence would have a random order, yet still have exactly 50/50 distribution of the outcomes. – pjs Dec 05 '20 at 17:52

4 Answers4

1

A simple random between 0 and 1 would do it.

private Random _rnd = new();
public string Randomization(string a, string b) {
    if (_rnd.Next(2) == 0) {
        return a;
    }
    return b;
}

Random.Next

Edit: It is better to create the Random object once, so outside of the function (for numerous reason).

Observer
  • 122
  • 6
1

You can just use NextDouble() as follows:

public string Randomization(string a, string b)
{
    return new Random().NextDouble() < 0.5 ? a : b;
}

The solution will also work with Next(int maxValue). However, if the method is being called enough times so that performance might be worth considering, NextDouble() will be a better option.

Here's the source code for both of these methods:

public virtual int Next(int maxValue) {
    if (maxValue<0) {
        throw new ArgumentOutOfRangeException("maxValue", Environment.GetResourceString("ArgumentOutOfRange_MustBePositive", "maxValue"));
    }
    Contract.EndContractBlock();
    return (int)(Sample()*maxValue);
}

public virtual double NextDouble() {
    return Sample();
}

Here's the reference: https://github.com/Microsoft/referencesource/blob/master/mscorlib/system/random.cs#L181

One more point regarding performance. You should move the instantiation of the Random class outside of the Randomization() method.

Thiago Cordeiro
  • 105
  • 1
  • 5
1

You could also use a method that takes a string array. Then you don't have to create a new method if you have more strings.

Also, you should make the Random object a property or field. Otherwise, the method returns the same string if you call it often in a few milliseconds.

A method like that would be something like:

Random random = new Random();
public string Randomization(params string[] elements) {
      return elements[random.Next(elements.Length)];
}

For your case, because of the params keyword, usage would remain the same.

string result = Randomization("a", "b");
Thiago Cordeiro
  • 105
  • 1
  • 5
Gidyyy
  • 101
  • 1
  • 4
0

If you must have an 50% distribution across the two values i.e if a was returned before, next time it should be b, you may consider the below logic.

I have used lock to support thread safety. You can remove them if there is no multi threading requirement. I have used a singleton pattern instead of static variable. Based on your need, you may simplify the code to use static variables instead of singleton.

The first determination is done by the checking the second the object is creating is odd or even.

using System;

public class Program
{
    public static void Main()
    {
        Console.WriteLine(Singleton.Instance.Randomization("one", "two"));
        Console.WriteLine(Singleton.Instance.Randomization("one", "two"));
        Console.WriteLine(Singleton.Instance.Randomization("one", "two"));
        Console.WriteLine(Singleton.Instance.Randomization("one", "two"));
        Console.WriteLine(Singleton.Instance.Randomization("one", "two"));
        Console.WriteLine(Singleton.Instance.Randomization("one", "two"));
    }
}

public sealed class Singleton
{
    private static readonly Lazy<Singleton> lazy = new Lazy<Singleton>(() => new Singleton());
    public static Singleton Instance
    {
        get
        {
            return lazy.Value;
        }
    }

    private static readonly object _lock = new Object();
    private bool _counter;
    private Singleton()
    {
        this._counter = DateTime.Now.Second % 2 == 0;
    }

    public string Randomization(string a, string b)
    {
        lock (_lock)
        {
            _counter = !_counter;
            return _counter ? a : b;
        }
    }
}
Ramesh
  • 13,043
  • 3
  • 52
  • 88