The below code is copied from a paper, undergrad work was linked to from a wikipedia page. I believe I've spotted some flaws in the paper and some in the code but as I have no C# experience I just want to double check.
My understanding is that this code was meant to create a large psuedo totally random number but instead I believe it creates a large number which is a reoccuring smaller random number.
ie. 123123123 instead of 123784675. Can someone please confirm what the code does.
What I read here http://csharpindepth.com/Articles/Chapter12/Random.aspx and on Stackoverflow in various posts makes me believe that it's using the same seed and hence getting the same number each iteration and just appending that same number over and over.
Random randomNumber = new Random();
counter = 0;
for (int j = 0; j < 1; j++)
{
StringBuilder largeRandomNumber = new StringBuilder();
for (int i = 0; i < 40000; i++)
{
int value = randomNumber.Next(11111, 99999);
largeRandomNumber.Append(value);
}
}
Creates instance of random and loops through creating the next random number using random.Next(int min, int max) and appends this on the end of a string. Essentially, it just creates one huge number for something. Outer loop is garbage, not needed at all. Random doesn't need to be seeded again after creation...keeps same seed and progresses correctly using the Next method. Everything about this code "works" but seems pointless in any application besides learning about the random class.
The code is fine.
Try it here: http://www.compileonline.com/compile_csharp_online.php
using System.IO;
using System;
using System.Text;
class Program
{
static void Main()
{
Random randomNumber = new Random();
for (int j = 0; j < 1; j++)
{
StringBuilder largeRandomNumber = new StringBuilder();
for (int i = 0; i < 40; i++)
{
int value = randomNumber.Next(11111, 99999);
Console.WriteLine(value);
}
}
}
}
It is correct. Yes, Seed is same but this line will make sure that you get different number on different run :
int value = randomNumber.Next(11111, 99999);
and since you are appending this number to a string to create large random number, this does what it was supposed to do.
randomNumber is seeded on construction. randomNumber.Next is returning the next random integer between the two given integers based on the initial seed, and is not reseeded, thus giving 40000 new random numbers and appending them.
Not sure what the outer loop is for, it only runs once anyway
Yes, it is most likely that it will generate the same number if called quickly in succession, since Random is seeded with the current time. Unless they instantiated the randomNumber instance inside the loop however, for purposes of an example it works fine.
For example, if the code is plugged into a function like this
public string GetLargeRandomNumber()
{
Random randomNumber = new Random();
StringBuilder largeRandomNumber = new StringBuilder();
for (int j = 0; j < 1; j++)
{
for (int i = 0; i < 40000; i++)
{
int value = randomNumber.Next(11111, 99999);
largeRandomNumber.Append(value);
}
}
return largeRandomNumber.ToString();
}
And called from a main function in quick succession it will return the same random number.
Related
I'm trying to create an array list using random numbers. But sometimes I get a zero in results. I do not understand why.
I'm grateful if anyone can explain.
int[] number = new int[6];
Random rnd = new Random();
for (int i = 0; i < number.Length; i++)
{
int random = rnd.Next(1, 26);
if (!number.Contains(random))
{
number[i] = random;
}
}
foreach (int nr in number)
{
Console.Write("|" + nr + "|");
}
//results
|6||12||0||22||25||11|
int[] number = new int[6];
Here number array is created with default int value i.e 0
The issue with your code is in some cases this value is not getting updated due to the check
if (!number.Contains(random))
You can change your code to include a loop to guarantee your random number doesn't lie in the array.
int[] number = new int[6];
Random rnd = new Random();
for (int i = 0; i < number.Length; i++)
{
int random = rnd.Next(1, 26);
while (number.Contains(random))
{
random = rnd.Next(1, 26);
}
number[i] = random;
}
foreach (int nr in number)
{
Console.Write("|" + nr + "|");
}
Please note that current approach is quite performance hungry as for every new random value we are iterating through entire array everytime to check if it exists. You can reduce the performance by using as HashSet<int> if possible
When you declare the array in following statement it initializes with 6 integers as 0
int[] number = new int[6];
While the random number generated for each array element, check for duplication in following statement may have resulted false
if (!number.Contains(random))
That's why it was never updated to new assigned number.
You can add else condition to it and regenerate random number
Just use your debugger to step through your code and inspect your variables to see what's happening. Apart from all the suggestions here, which are bad because they can loop way too many times or even forever, you appear to want to get 6 random, unique numbers between 1 and 26.
The de facto way to do that, is to generate a list with those numbers (Enumerable.Range()), shuffle them (Fisher-Yates) and Take() the first six.
Use while loop.
int[] number = new int[6];
Random rnd = new Random();
int i = 0;
while (i < number.Length)
{
int random = rnd.Next(1, 26);
if (!number.Contains(random))
{
number[i] = random;
i++;
}
}
foreach (int nr in number)
{
Console.Write("|" + nr + "|");
}
I'm kinda new to array and I made a char array (with 174 things in it) but I don't know how to output it in a randomize way. I'm trying to make a secured code for my system. I wanted to output 13 char from that 174 char array into a textbox, but I don't think I get the logic. Thank you in advance! Here is the code that only outputs 1 char per button click:
Random rnd = new Random();
int randomnum = rnd.Next(0, 174);
for (int x = 0; x <= 13; x++)
{
textBox11.Text = chararray[randomnum];
}
Your code is almost there, but there are a few issues:
You need to append the new character to the end of the string as apposed to just setting the Text value directly. You can do this easily with += instead of =.
You need to pick a different random character for each iteration of the loop, so move your call to .Next inside the for.
Putting this together you'd have something like this:
Random rnd = new Random();
for (int x = 0; x <= 13; x++)
{
int randomnum = rnd.Next(0, 174);
textBox11.Text += chararray[randomnum];
}
Note however, that if this is for the purpose of security, using Random isn't great. You should probably use something like the RNGCryptoServiceProvider. For example:
using (var rng = new RNGCryptoServiceProvider())
{
byte[] password = new byte[10];
rng.GetBytes(password);
textBox11.Text = Convert.ToBase64String(password).Remove(13);
}
I've attached a screenshot of this code working. I had a small typo
This will change the seed for random
int seed = 1;
Create an instance of Random, we don't need to recreate it every time we need to use it
Random r = new Random(seed);
This only initializes the characters
char[] _myChars = new char[170];
for(var i = 0; i < _myChars.Length; i++)
{
_myChars[i] = (char)(i%26 + 65);
}
This is the query you're looking for, it will query the characters and order them by a random order with r.Next()
var output = _myChars.OrderBy(o => r.Next()).Take(13).ToList();
This is only for displaying the output, you would want to use the output in your textbox
for(var i = 0; i < output.Count; i++)
{
Console.WriteLine(output[i]);
}
Console.ReadLine();
I have an array of integers called cards[52]. Each element contains an integer that represents a card (cards[0] = 5 would represent the 6 of clubs for example).
This is how I shuffled the array. It works, but I am getting repeats.
private void shuffleCards()
{
for (int i = 0; i < cards.Length; i++)
{
int randIndex = r.Next(0, 52);
int origCard = cards[i];
cards[i] = cards[randIndex];
cards[randIndex] = origCard;
}
}
r is the Random variable I initialized in the beginning of the program.
When testing the program, I noticed I would get the same card 2 or 3 times. Obviously I cannot get repeats, they all must be different. I can't see in any way how this method gives me repeats.
How can I shuffle this array without any repeats? Thanks.
EDIT
Okay, turns out the shuffle function wasn't the problem. It is the deal() function that is causing the problem.
private void deal()
{
for (int i = 0; i < 26; i++)
{
userCards[i] = cards[i];
setUserValue(); //ignore this
}
for (int i = 26; i < 52; i++)
{
opponentCards[i - 26] = cards[i];
setOpponentValue(); //ignore this
}
}
I know for sure it isn't the shuffle function. I printed the results of all the cards to a text file and saw no iterations. However, when the cards are dealt to the user and the opponent, that's when all the iterations occur. Any advice?
There is very simple algorithm known as Fisher Yates shuffling algorithm which does the shuffling in O(n) time and O(1) space complexity.
Use a random function that generates a random index from the given set and replace the random element generated with the last index. Decrement last index and continue like this for the rest of elements.
Let the array of size n be : arr[n]
void randomize ( int arr[], int n )
{
// Use a different seed value so that we don't get same
// result each time we run this program
srand ( time(NULL) );
// Start from the last element and swap one by one. We don't
// need to run for the first element that's why i > 0
for (int i = n-1; i > 0; i--)
{
// Pick a random index from 0 to i
int j = rand() % (i+1);
// Swap arr[i] with the element at random index
swap(&arr[i], &arr[j]);
}
}
Source : Algorithm
// in general i take random colors from an Enum and insert that into a new array.
when i ask by BoxMessage inside the loop For each Array[i] i get random colors as expected.
If i comment (\) the message box and ask for Array[1-5] outside the loop, i get the same color for all 5 message box.
I believe it related to the fact that my message box inside the loop successfully convert the Enum into a string, when i tried to convert the whole array in the loop ( array[i].ToString(); ) it didn't quite work.
please advise....
public void GetArray()
{
array = new EnumColor[5];
for (int i = 0; i < 5; i++)
{
rnd = new Random();
int rndnum = rnd.Next(0, 4);
array[i] = (EnumColor)rndnum;
MessageBox.Show(array[i].ToString());
}
MessageBox.Show(array[0].ToString());
MessageBox.Show(array[1].ToString());
MessageBox.Show(array[2].ToString());
MessageBox.Show(array[3].ToString());
MessageBox.Show(array[4].ToString());
}
for (int i = 0; i < 5; i++)
{
rnd = new Random();
int rndnum = rnd.Next(0, 4);
array[i] = (EnumColor)rndnum;
MessageBox.Show(array[i].ToString());
}
You're overwriting elements in the array, don't do this.
Retrieve elements into a temporary local variable instead (and use .Length instead of a hardcoded length)
The bug itself is caused by Random being incorrectly seeded, it's being regerated on every iteration.
Random rnd = new Random();
for (int i = 0; i < array.Length; i++)
{
int rndnum = rnd.Next(0, 4);
EnumColor selected = (EnumColor)array[i];
MessageBox.Show( selected .ToString() );
}
You are getting the same color because you are declaring random instance each time in your loop, just move the declaration outside:
rnd = new Random();
for (int i = 0; i < 5; i++)
{ ... }
If you like to learn more about why Random class works that way you can take a look at this answer.
The problem is indeed the Random being re-created for every loop. But here's the full explanation.
When you create a Random, it uses the Environment.TickCount as seed value. (milliseconds since system startup). So if your loop is fast enough, this will always be the same value, so the rnd.Next function will always return the same value.
So now for the tricky part.. why did it work with the messagebox inside the loop? By showing the message, the loop became slower by waiting for you clicking the ok button. Therefore the next loop, the seed was indeed changed. That's why you got another value.
For some coursework I need to generate a normal magic square through brute force, this is part of the code. fyi; I'm not allowed to use any classes other than the commonly used. (I'm probably pushing my luck with Math.Pow)
I have the following method to generate a 2 dimensional of size NxN:
static int[,] GenerateSquare(int n)
{
int[,] sqarray = new int[n,n];
int[] rndarray = new int[n];
//puts completely random integers from 1 to n^2 in all elements of the square array (sqarray)
for (int i = 0; i < n; i++)
{
rndarray = FullRndArray(n);
for (int j = 0; j < n; j++)
{
sqarray[i, j] = rndarray[j];
}
}
return sqarray;
}
The FullRndArray() method is below:
static int[] FullRndArray(int n)
{
//creates an array of size n and fills with random intigers between 1 and n^2
int[] rndarray = new int[n];
Random rnd = new Random();
int ntothe2 = Convert.ToInt32(Math.Pow(n, 2));
for (int i = 0; i < n; i++)
rndarray[i] = rnd.Next(1, ntothe2 + 1);
return rndarray;
}
The problem is that when i run this code, the contents of each line is random, but each line of the square is the same as the last (ie 1-1, 1-2, 1-3 are the same as 2-1, 2-2, 2-3 and the same as 3-1, 3-2, 3-3 respectively). Yet when i go through debugger line by line, i end up with a perfectly random set of numbers in every space. Can anyone explain this error to me please?
This is the culprit:
Random rnd = new Random();
Random numbers are generated starting from a seed: same seed means same not-so-random sequence of numbers. Random uses the current time as seed, so when you run your code it runs so fast that you are creating two Randoms with the same seed, which then produce two identical rows. On the other hand, when you are debugging you let enough time pass and everything goes as expected.
The solution is to create an instance of Random, static or at the beginning of GenerateSquare, and use that one for the whole process.
I got exactly the same behavior that you describe.
This seems to work :
static int[,] GenerateSquare(int n)
{
int[,] sqarray = new int[n, n];
int[] rndarray = new int[n];
Random rnd = new Random();
//puts completely random integers from 1 to n^2 in all elements of the square array (sqarray)
for (int i = 0; i < n; i++)
{
rndarray = FullRndArray(n, rnd);
for (int j = 0; j < n; j++)
{
sqarray[i, j] = rndarray[j];
}
}
return sqarray;
}
static int[] FullRndArray(int n, Random rnd)
{
//creates an array of size n and fills with random intigers between 1 and n^2
int[] rndarray = new int[n];
int ntothe2 = Convert.ToInt32(Math.Pow(n, 2));
for (int i = 0; i < n; i++)
rndarray[i] = rnd.Next(1, ntothe2 + 1);
return rndarray;
}
I understand we must use the Random.Next() method on the same instance in order to be "really" random (as described in the BlackBear answer).
It probably worked during debug because you induced time laps between steps.