I have this code snippet:
Random rand = new Random();
int chance = rand.Next(1, 101);
if (chance <= 25) // probability of 25%
{
Console.WriteLine("You win");
}
else
{
Console.WriteLine("You lose");
}
My question is, does it really calculate a 25% probability for winning here?
Is the chance of winning for the player here is really 25%?
Edit:
I just wrote this:
double total = 0;
double prob = 0;
Random rnd = new Random();
for (int i = 0; i < 100; i++)
{
double chance = rnd.Next(1, 101);
if (chance <= 25) prob++;
total++;
}
Console.WriteLine(prob / total);
Console.ReadKey();
And it's highly inaccurate. It goes from about 0.15 to 0.3.
But when I do more checks (change from (i < 100) to (i < 10000)) it's much more accurate.
Why is this? Why aren't 100 checks enough for it to be accurate?
This is very easy to check for yourself:
Random rand = new Random();
int yes = 0;
const int iterations = 10000000;
for (int i = 0; i < iterations; i++)
{
if (rand.Next(1, 101) <= 25)
{
yes++;
}
}
Console.WriteLine((float)yes/iterations);
the result:
0.2497914
The conslusion: Yes, yes it is.
Edit: Just for fun, the LINQy version:
Random rand = new Random();
const int iterations = 10000000;
int sum = Enumerable.Range(1, iterations)
.Count(i => rand.Next(1, 101) <= 25);
Console.WriteLine(sum / (float)iterations);
For most cases, I would say yes. However, you have to remember that most randomization algorithms use a pseudo-random generator, and so to some extent, you're at the mercy of the idiosyncrasies of that particular generator. I do agree with #AwokeKnowing that you can you also just do a random number between 1 and 4 and get the same result. I assume that the .Net randomization algorithm should suffice for most cases. For more info see:
http://en.wikipedia.org/wiki/Pseudorandom_number_generator
yes, that should work fine. just as >=75 would work too. if you just want 25%, you can go ahead and just do a random number between 1 and 4.
but please note, a 25% chance does NOT mean that out of 100 tries, he will win 25 times. It just means each time he has a 25% chance of winning. it's theoretically possible for him to win every single time. (but that will not happen, especially with a pseudo-random generator).
Internally the random number will be between 0 and 1 so it's just as random to use 4 as 1000, as far as that goes. add the parameter just projects it to the range you want.
Related
I have a situation in which I must generate a random number, this number must be either zero or one
So, the code is something like this:
randomNumber = new Random().Next(0,1)
However, the business requirements state that there is just 10% probability that the generated number is zero and 90% probability that the generated number is 1
However can I include that probability in generating the random number please?
What I thought of is:
Generate array of integer that includes 10 zeros and 90 ones.
Generate a random index between 1 and 100
Take the value that corresponds to that index
But I don't know if this way is the correct way, plus, I think that C# should have something ready for it
You can implement it like that:
// Do not re-create Random! Create it once only
// The simplest implementation - not thread-save
private static Random s_Generator = new Random();
...
// you can easiliy update the margin if you want, say, 91.234%
const double margin = 90.0 / 100.0;
int result = s_Generator.NextDouble() <= margin ? 1 : 0;
to get true with a probability of 10%:
bool result = new Random().Next(1, 11) % 10 == 0;
to get true with a probability of 40%:
bool result = new Random().Next(1, 11) > 6;
First of all, you should save the reference to the random instance in order to get a proper random sequence of numbers:
Random randGen = new Random();
The second thing to know, is that the max of the random is exclusive, so to properly solve the issue you should do:
int eitherOneOrZero = randGen.Next(1, 11) % 10;
To generalize it to any variation of chances, you can do:
Random randGen = new Random();
var trueChance = 60;
int x = randGen.Next(0, 100) < trueChance ? 1 : 0;
Testing:
Random randGen = new Random();
var trueChance = 60;
var totalCount = 1000;
var trueCount = 0;
var falseCount = 0;
for (int i = 0; i < totalCount; i++)
{
int x = randGen.Next(0, 100) < trueChance ? 1 : 0;
if (x == 1)
{
trueCount++;
}
else
{
falseCount++;
}
}
Output:
True: 60.30 %
False: 39.70 %
I am assigning employees a random integer percentage of 100. This percentage is based on how many employees we have and must total to 100.
If we have 4 employees, I would perhaps want to generate a split such as 80-10-5-5.. if we had 2 employees. The more random the percentages are, the better.
I'm not sure how to accomplish this elegantly without a ton of different if statements but even then the randomness would be limited I feel.
Just assign each employee a random number in a certain range (range ist up to you). Than calculate the sum of the random numbers. Last step: devide each random number by the sum which gives you the percentage.
Example: random number 3, 9, 7
Sum = 19
Percentages: 3/19=16%, 9/19=47%, 7/19=37%
(Values are rounded.)
I have written a sample code for this:
int no_of_employees = 4;
int total_percentage = 100;
List<int> tempNumberList = new List<int>();
List<int> finalNumberList = new List<int>();
Random random = new Random();
for (int i = 0; i < no_of_employees; i++)
{
tempNumberList.Add(random.Next(total_percentage));
}
int sum = tempNumberList.Sum();
foreach(int number in tempNumberList)
{
finalNumberList.Add((number * total_percentage) / sum);
}
if(finalNumberList.Sum() != total_percentage)
{
finalNumberList[0] = finalNumberList[0] + (total_percentage - finalNumberList.Sum());
}
Please feel free to improve the logic if necessary at all.
This should work:
var random = new Random();
var percentages = new List<int>();
int remainder = 100;
for (int i = 0; i < employeesCount; i++)
{
int percentage = random.Next(remainder);
percentages.Add(percentage);
remainder -= percentage;
}
percentages[percentages.Count - 1] += remainder;
Note that
the last line solves the rounding issue in case the percentages' sum is not 100
a solution using only LINQ is also doable although less readable and probably with an impact on performance (using Aggregate for instance introduces the creation of an anonymous type)
I'm not 100% sure this solution guarantees equal probability (especially the last employee's case)
How can i generate different random numbers in short time?
For example:
Number = 20;
if (Number > 0)
{
AddEffect(rand.Next(0,100);
Number--;
}
In this example, rand.Next gives me twenty times the same number. Is there any way to force a change?
I think you're trying to say:
var rand = new Random();
var Number = 20;
while (Number > 0)
{
// rand.Next(0,100); // this will give 20 different numbers btw
AddEffect(rand.Next(0,100));
Number--;
}
but otherwise, seems fine
int totalNumbers = 20;
Random rand = new Random();
for (int i = 0; i < totalNumbers; i++)
{
AddEffect(rand.Next(0, 101)); // a number between -1 and 101, min: 0, max: 100
}
Is this what you mean? This is an easy and clear way to generate some random numbers.
More info here: http://www.dotnetperls.com/for
Example:
Starting number: 0
Finish number: 147
Choose a random number in the range 1-26. Increment the starting number by this number, continually getting another random number until we reach the finish number.
That is, if we are at 137 it means the random number has to be between 1 and 10. When we reach 144, between 1 and 3 and so on. I've tried using modulo to no avail.
Example of code I've tried:
int start = 0;
int finish = 0;
int highest = 26;
while(start <= finish) {
int modulo = start % finish % highest;
int random = (new Random()).Next(modulo);
start += random;
}
Any ideas?
It is a lot better essential to move the Random instance out of the loop. Otherwise all your values except the last few will be the same.
To get a number in your your dynamic range, there is the Random method
Next(int minValueInclusive, int maxValueExclusive)
int finish = 147;
// untested
var generator = new Random(); // outside the loop
while(start < finish) // stop when equal
{
int range = finish-start;
if (range > highest) range = highest;
int random = generator.Next(1, range+1);
start += random;
Console.Write('A' + random - 1); // check
}
My first observation of the example you posted, assuming it's an example that you actually tried, is that start
int modulo = start % finish % highest;
is going to result in a division by 0 error because finish is 0.
Secondly, I think what you want to replace that line with
int modulo = (finish - start) % highest;
It makes more sense for the first term to be the distance from start to finish, because that's the limit you don't want to exceed when you add your next random number.
Within your loop, you need to logically run through these steps:
What current number am I at? (start)
How far am I from the finish? (var distance = finish - start)
Am I farther than 26 from the finish? If so, my max is 25. Else, my max is however far I am from the finish ( var max = distance % 26 ) or you can use a full if statement if the modulo is confusing
Generate a new random number between 1 and max.
it would look something like this:
int start = 0;
int finish = 144;
int highest = 26;
var rng = new Random();
while(start <= finish) {
var distance = (finish - start);
var maxRange = distance % highest
start += rng.Next(1,maxRange +1 );
}
(The modulo means you will be within 0 and 25 always)
This should work, just need a simple if in the loop. No modulo needed.
int current = 0;
int high = 26;
int rand = 0;
int range;
while (current != 147)
{
range = 147 - current;
if (range < high)
{
high = range;
}
rand = (new Random().Next(1, high));
current += rand;
}
I created a Windows Forms application using Visual Studio Professional in C#. In my program I prompt the user to input the number of rolls he/she wants and then they press enter to get the numbers.
The numbers are shown in the same form under a label and get tallied up. I know how to tally the numbers know but I can't get the random number generator to generate the number of rolls the user inputs.
This is what i am doing:
Random randGen = new Random;
int oneRoll = randGen.Next(1,7) + randGen(1, 7);
I want the same program to occur the number of times the user wants. I tried a for loop but couldn't get what I wanted.
Make sure you create the Random Number generator just once.
Do NOT create it in each loop iteration.
Or, the numbers may not be random because the loop is so tight it will use the same time as the seed in the internal generator.
Try something like this:
Random randGen = new Random();
var rolls = new List<int>();
int sum = 0;
for (int i = 0; i < numberOfRolls; i++)
{
int randomNum1 = randGen.Next(1,7);
int randomNum2 = randGen.Next(1,7);
sum += randomNum1 + randomNum2;
rolls.Add(randomNum1);
rolls.Add(randomNum2);
}
Now all the separate rolls are in rolls, and the sum of them has already been calculated.
Edited to roll two dice, record them individually, and sum it all together.
int rolls = Console.ReadLine();
int total = 0;
Random randGen = new Random(System.DateTime.Now.Millisecond);
for(int i =0; i<rolls; i++)
{
int oneRoll = randGen.Next(1,7) + randGen.Next(1, 7);
Console.WriteLine("Rolled " + oneRoll);
total += oneRoll;
}
Console.WriteLine("Total " + total);
NB. you don't need the Millisecond bit, the seed just makes it more random
Your code is totally wrong...
Random randGen = new Random(DateTime.Now.Ticks); // unique seed, mostly
int result = 0;
for (int i = 0; i < number_of_rolls_the_user_wants; i++)
result += randGen.Next(2, 14); // (1 - 7) + (1 - 7) = 2 - 14 lol... >.>
Replace number_of_rolls_the_user_wants with the number of rolls the user wants.
result will hold the result.
Also please note that, if you generate many random numbers in a short time, use the same Random object!