This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
c# random string generator
I need to generate a random string with a given length. This is my code so far. The problem is the random string is like "RRRRRR" or "SSSSS" The same letter every time. Just when i restart the app the letter change. I need something like "asrDvgDgREGd"
public string GenerateChar()
{
Random random = new Random();
return Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65))).ToString();
}
public string GenerateChar(int count)
{
string randomString = "";
for (int i = 0; i < count; i++)
{
nahodneZnaky += GenerateChar();
}
return randomString;
}
Try using the same random object for the whole string, rather than initializing one for each char.
The random object will generate a "pseudo-random" number, based on mathematical progressions starting from a "seed" number. You can actually get the same sequence of "random" numbers if you initialize the Random object to the same seed every time.
Now, when you initialize Random without specifying a seed, it'll take the computer's clock as seed. In this case, you're probably doing it fast enough that the clock hasn't changed from one initialization to another, and you get always get the same seed.
You're better off initializing the Random object in your function that generates the random string, and passing it as a parameter to the GenerateChar function, so that you're calling NextDouble() several times on the same instance of the Random object, instead of only once on different instances of it.
Don't create a new instance of Random on each iteration - that's going to seed each instance with the current time in milliseconds, which obviously isn't likely to change between iterations.
Create a single instance of Random, and pass it into the method. I'd also advise you not to concatenate strings like that in a loop, or even to create that many strings. Additionally, if you use Random.Next(int, int) to make your life a lot easier.
Try this:
public char GenerateChar(Random rng)
{
// 'Z' + 1 because the range is exclusive
return (char) (rng.Next('A', 'Z' + 1));
}
public string GenerateString(Random rng, int length)
{
char[] letters = new char[length];
for (int i = 0; i < length; i++)
{
letters[i] = GenerateChar(rng);
}
return new string(letters);
}
private static readonly Random SingleRandom = new Random();
public string GenerateStringNotThreadSafe(int length)
{
return GenerateString(SingleRandom, length);
}
Now it's worth being aware that Random isn't thread-safe, so if you've got multiple threads you shouldn't just have a single instance of Random in a static variable without locking. There are various ways around this - either create a subclass of Random which is thread-safe, or a set of static methods which do the same thing, or use thread-local variables to have one instance per thread.
I have a StaticRandom class as part of MiscUtil but these days I'm leaning towards the thread-local version and passing it down the chain where appropriate. One day I'll add that as another option to MiscUtil...
You could save yourself the hassle and use Membership.GeneratePassword method. It is essentially doing what you require.
Usage:
int passwordLength = 5;
int alphaNumericalCharsAllowed = 2;
string random = Membership.GeneratePassword(passwordLength, alphaNumericalCharsAllowed);
For readability aswell you could wrap this in a helper method:
private string GenerateRandomString(int length, int alphaNumericalChars)
{
return Membership.GeneratePassword(length, alphaNumericalChars);
}
Nothing special, but short. 32 and 127 are min and max range of chars you want to be generated.
public static string GetRandomString(int length)
{
var r = new Random();
return new String(Enumerable.Range(0, length).Select(n => (Char)(r.Next(32, 127))).ToArray());
}
I know this might not be the best solution, but I kind of like the idea to be able to specify "allowed" characters:
private const int _defaultNumberOfCharacters = 8;
private const int _defaultExpireDays = 10;
private static readonly string _allowedCharacters = "bcdfghjklmnpqrstvxz0123456789";
public static string GenerateKey(int numberOfCharacters)
{
const int from = 0;
int to = _allowedCharacters.Length;
Random r = new Random();
StringBuilder qs = new StringBuilder();
for (int i = 0; i < numberOfCharacters; i++)
{
qs.Append(_allowedCharacters.Substring(r.Next(from, to), 1));
}
return qs.ToString();
}
Maybe you can find the Path.GetRandomFileName method useful, depending on the exact characters you need in the string.
Try static
public string GenerateChar()
{
static Random random = new Random();
return Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65))).ToString();
}
http://msdn.microsoft.com/en-us/library/system.io.path.getrandomfilename.aspx
string randomName = Path.GetRandomFileName();
randomName = randomName.Replace(".", string.Empty);
// take substring...
Pass random from the calling method and initialise it once - you are reseeding the Random generator with the same seed each time....
You should initialize your random variable outside the method:
public Random random = new Random();
public string GenerateChar()
{
return Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65))).ToString();
}
...
Try this out.
public string GetRandomString()
{
int randomNumber = new Random().Next();
string RandomString = string.Empty;
for(int i = 0;i < randomNumber.ToString().Length;i++)
{
RandomString += ((char)Convert.ToUInt32(randomNumber.ToString()[i])).ToString();
}
return RandomString;
}
Related
I am looking for a function that will return a seed of C# Random class based on the first two int numbers produced by Random.Next(). I would like to avoid brute force (this is what I tried). Essentially, I am looking for a reverse function for this code, that is not based on brute force
using System;
public class Program
{
public static void Main()
{
int seed = 0;
Random rnd = new Random(seed);
Console.WriteLine($"Seed: {seed}");
Console.WriteLine($"Rnd1: {rnd.Next()}");
Console.WriteLine($"Rnd2: {rnd.Next()}");
}
}
Which prints out
Seed: 0
Rnd1: 1559595546
Rnd2: 1755192844
Is there a fast way to obtain Seed given Rnd1 and Rnd2?
Hi one possible to get the seed, but without rnd1 and rnd2 would be to do the following
var tickCount = Environment.TickCount;
var random = new Random();
var seededRandom = new Random(tickCount);
for (int i = 0; i < 100000000; i++)
{
// Does not enter the if case at any point.
if (random.Next() != seededRandom.Next())
{
Console.WriteLine("No match");
}
}
Source: http://referencesource.microsoft.com/#mscorlib/system/random.cs,53
This question already has answers here:
Random number generator only generating one random number
(15 answers)
Closed 6 years ago.
I am new to C#, I have a code that calls the same function 3 times that returns a random sting. For some reason my code is returning the same string all the time. Please help.
public static String randomString()
{
String chars = "QWERTYUIOPASDFGHJKLZXCVBNM";
Random rand = new Random();
String finalstring = null;
for (int i = 0; i < 8; i++)
{
finalstring += chars[rand.Next(0, chars.Length - 1)];
}
return finalstring;
}
public void SecondTest()
{
Console.WriteLine(Class1.randomString());
Console.WriteLine(Class1.randomString());
Console.WriteLine(Class1.randomString());
}
Sample Output observing:
AXCFSDRG
AXCFSDRG
AXCFSDRG
You're constructing three separate Random objects, rather than reusing a single Random object (which would be better practice).
Random objects, if you don't provide a seed, are seeded with the current time. In this case, your randomString() method returns so fast that all three Random objects get the same seed, and thus get the same sequence of outputs.
Based from this SO Answer.
Every time you do new Random() it is initialized using the clock. This
means that in a tight loop you get the same value lots of times. You
should keep a single Random instance and keep using Next on the same
instance.
//Function to get random number
private static readonly Random random = new Random();
private static readonly object syncLock = new object();
public static int RandomNumber(int min, int max)
{
lock(syncLock) { // synchronize
return random.Next(min, max);
}
}
Use RNGCryptoServiceProvider class:
https://msdn.microsoft.com/en-us/library/system.security.cryptography.rngcryptoserviceprovider(v=vs.110).aspx
Look at RNGCryptoServiceProvider: generate random numbers in the range [0, randomMax)
If you use the extension method in the answer and the following:
public static String randomString()
{
String chars = "QWERTYUIOPASDFGHJKLZXCVBNM";
Random rand = new Random();
String finalstring = null;
for (int i = 0; i < 8; i++)
{
finalstring += chars[GenerateRandomNumber(8)];
}
return finalstring;
}
public static int GenerateRandomNumber(int length)
{
using (var randomNumberGenerator = new RNGCryptoServiceProvider())
{
return randomNumberGenerator.GetNextInt32(length);
}
}
The result will be different each time.
I made a lottery program : http://yadi.sk/d/bBKefn9g4OC7s
Here is the whole source code : http://yadi.sk/d/rnQMfrry4O8cu
Random rnd = new Random();
int[] loto;
loto = new int[7];
for (int f = 1; f <= 6; f++) {
loto[f] = rnd.Next(1, 50); // Generating random number between 1-49
for (int h = 1; h < f; h++) {
if (loto[f] == loto[h]) { // Check with other numbers for the case of duplicate
loto[f] = rnd.Next(1, 50); // If there is a duplicate create that number again
}
}
}
This section I'm generating random 6 different numbers between 1-49
Also I'm wondering in this example, are nested loops increase the spontaneity ?
I'm getting 3-4 max, this program wrong or am I so unlucky ?
( note that : that's my first program )
For all guys trying to help me : I'm really beginner on programming(c# yesterday | c++ 3 weeks i guess), and if you guys clarify what you mean in codes it'll be great.
And please not give me extreme hard coding examples( I don't wanna quit c# )
Your method looks unsafe, as get value from Random again in the inner loop does not guarantee that it will return unduplicated value. For low value as 1-49, you can use simple random-picking algorithm like this
var numbers = new List<int>();
for (int i = 1; i <= 49; i++) {
numbers.Add(i);
}
Random r = new Random();
var loto = new int[6];
for (int f = 0; f < 6; f++) {
int idx = r.Next(0, numbers.Count);
loto[f] = numbers[idx];
numbers.RemoveAt(idx);
}
Note that this is far from optimal solution in terms of performance, but if you will run it only once in a few seconds or more so it should be fine.
I think it's correct except for the for loop declaration: remember that arrays in C# are zero-based. Thus the loop should look like this:
for (int f = 0; f < 7; f++)
or even better:
for (int f = 0; f < loto.Length; f++)
Update: I cannot comment the other answers (too less reputation), thus I have to post it here:
#Dan: only one loop is not correct as it is not allowed to have the same number twice in Loto. In his inner loop, 1342 checks if the created random number already exists, so it is not correct to leave it out.
#James: As 1342 just started programming, it is not necessary to use a static field in my opinion. I guess that he or she has his whole code in the Main method so there is no benefit using a static variable.
There are a few issues here - you've got one too many loops for a start, and no comments.
See this (over-commented) example below:
// This is static so we don't recreate it every time.
private static Random _rnd;
static void Main(string[] args)
{
_rnd = new Random();
// You can declare and initialise a variable in one statement.
// In this case you want the array size to be 6, not 7!
Int32[] lotoNumbers = new Int32[6];
// Generate 10 sets of 6 random numbers
for (int i = 0; i < 10; i++)
{
// Use a meaningful name for your iteration variable
// In this case I used 'idx' as in 'index'
// Arrays in c# are 0-based, so your lotto array has
// 6 elements - [0] to [5]
for (Int32 idx = 0; idx < 6; idx++)
{
// Keep looping until we have a unique number
int proposedNumber;
do
{
proposedNumber = _rnd.Next(1, 50);
} while (lotoNumbers.Contains(proposedNumber));
// Assign the unique proposed number to your array
lotoNumbers[idx] = proposedNumber;
}
}
}
You should end up with a 6 element long array with 6 random numbers between 1 and 50 in it.
Hope that helps!
Edit:
It's also well worth taking note of James' answer - if you're doing the above in a loop, you'll get the same values every time from Random, due to how the seed is used. Using a static version of Random will give much better results.
You don't want to keep re-creating a new instance of Random each time, that's the likely cause of why you keep getting similar values each time. The better approach is to create a static instance of Random and use that across your entire app - this should give you more realistic results e.g.
using System.Collections.Generic;
using System.Linq;
...
static readonly Random rand = new Random();
...
List<int> lottoNumbers = new List<int>(6);
int drawnNumber = -1;
for (int i = 0; i < lottoNumbers.Count; i++) {
do
{
drawnNumber = rand.Next(1, 50); // generate random number
}
while (lottoNumbers.Contains(drawnNumber)) // keep generating random numbers until we get one which hasn't already been drawn
lottoNumbers[i] = drawnNumber; // set the lotto number
}
// print results
foreach (var n in lottoNumbers)
Console.WriteLine(n);
For easily testing it, I have left the console logs and static void main for you.
You do not need two iterations for this. Also - arrays are 0 based, so either f has to be equal to 0, or less than 7. I went with equal 0 below.
I have created a recursive method which creates a new value and checks if the array contains the value. If it does not contain it, it adds it. But if it does contain it, the method calls itself to find a new value. It will continue to do this until a new value is found.
Recursive methods are methods which call themselves. Don't try and fill an array with an index bigger than 50 with this, as you will get an endless loop.
private static readonly Random Rnd = new Random();
static void Main(string[] args)
{
var loto = new int[7];
for (int f = 0; f <= 6; f++)
{
var randomValue = GetRandomNumberNotInArr(loto);
Console.WriteLine(randomValue);
loto[f] = randomValue;
}
Console.Read();
}
/// <summary>
/// Finds a new random value to insert into arr. If arr already contains this another
///random value will be found.
/// </summary>
/// <param name="arr">arr with already found values</param>
/// <returns></returns>
private static int GetRandomNumberNotInArr(int[] arr)
{
var next = Rnd.Next(1, 50);
return !arr.Contains(next) ? next : GetRandomNumberNotInArr(arr);
}
I can see that you are trying to simulate drawing 6 lottery numbers between 1 and 50.
Your code has some logic errors, but rather than fixing it I'm going to suggest doing it a different way.
There are several ways to approach this; a common one is this:
Create an empty collection of numbers.
while there aren't enough numbers in the collection
let randomNumber = new random number in the appropriate range
if (randomNumber isn't already in the collection)
add randomNumber to the collection
But there's another approach which scales nicely, so I'll demonstrate this one (someone else will probably already have written about the other approach):
Add to a collection all the numbers you want to choose from
Randomly rearrange (shuffle) the numbers in the collection
Draw the required number of items from the collection
This is pretty much what happens in a real-life lottery.
To shuffle a collection we can use the Fisher-Yates Shuffle. Here's an implementation:
/// <summary>Used to shuffle collections.</summary>
public class Shuffler
{
/// <summary>Shuffles the specified array.</summary>
/// <typeparam name="T">The type of the array elements.</typeparam>
/// <param name="array">The array to shuffle.</param>
public void Shuffle<T>(IList<T> array)
{
for (int n = array.Count; n > 1;)
{
int k = _rng.Next(n);
--n;
T temp = array[n];
array[n] = array[k];
array[k] = temp;
}
}
private readonly Random _rng = new Random();
}
Here's a full compilable example. I've avoided using Linq in this example because I don't want to confuse you!
using System;
using System.Collections.Generic;
namespace Demo
{
public static class Program
{
private static void Main()
{
int[] lotoDraw = createDraw();
Shuffler shuffler = new Shuffler();
shuffler.Shuffle(lotoDraw); // Now they are randomly ordered.
// We want 6 numbers, so we just draw the first 6:
int[] loto = draw(lotoDraw, 6);
// Print them out;
foreach (int ball in loto)
Console.WriteLine(ball);
}
private static int[] draw(int[] bag, int n) // Draws the first n items
{ // from the bag
int[] result = new int[n];
for (int i = 0; i < n; ++i)
result[i] = bag[i];
return result;
}
private static int[] createDraw() // Creates a collection of numbers
{ // from 1..50 to draw from.
int[] result = new int[50];
for (int i = 0; i < 50; ++i)
result[i] = i + 1;
return result;
}
}
public class Shuffler
{
public void Shuffle<T>(IList<T> list)
{
for (int n = list.Count; n > 1; )
{
int k = _rng.Next(n);
--n;
T temp = list[n];
list[n] = list[k];
list[k] = temp;
}
}
private readonly Random _rng = new Random();
}
}
I'm trying to create a binary search tree with unique random numbers. I'm using SortedSet to represent my tree and then I make it into an array and then I use Contains to see if a certain number is in the tree. My problem is that I can't figure out how to get all the random numbers different in a simple way. I used the methods Unik and Nålen_Unik but in this code it only generates 1 number to the array
Random random = new Random();
Program Tal = new Program();
string nål = Tal.Nålen_Unik();
string TalIArray = Tal.Unik();
bool found = false;
SortedSet<string> Tree = new SortedSet<string>();
for (int x = 0; x < 50000; x++)
{
Tree.Add(TalIArray);
}
int y = 0;
string[] TreeArray = Tree.ToArray<string>();
while (y < TreeArray.Length)
{
Console.WriteLine(TreeArray[y]);
y = y + 1;
}
private string Unik()
{
int maxSize = 4;
char[] chars = new char[10000];
string a;
a = "0123456789";
chars = a.ToCharArray();
int size = maxSize;
byte[] data = new byte[1];
RNGCryptoServiceProvider crypto = new RNGCryptoServiceProvider();
crypto.GetNonZeroBytes(data);
size = maxSize;
data = new byte[size];
crypto.GetNonZeroBytes(data);
StringBuilder result = new StringBuilder(size);
foreach (byte b in data)
{
result.Append(chars[b % (chars.Length - 1)]);
}
return result.ToString();
}
private string Nålen_Unik()
{
int maxSize = 1;
char[] chars = new char[62];
string a;
a = "0123456789";
chars = a.ToCharArray();
int size = maxSize;
byte[] data = new byte[1];
RNGCryptoServiceProvider crypto = new RNGCryptoServiceProvider();
crypto.GetNonZeroBytes(data);
size = maxSize;
data = new byte[size];
crypto.GetNonZeroBytes(data);
StringBuilder result = new StringBuilder(size);
foreach (byte b in data)
{
result.Append(chars[b % (chars.Length - 1)]);
}
return result.ToString();
There are mainly three approaches that are used to get random numbers without collisions:
Keep all numbers that you have picked, so that you can check a new number against all previous.
Create a range of unique numbers, shuffle them, and pick one at a time from the result.
Create such a huge random number that the risk of collisions is so small that it's negligible.
The second approach is the same principle as shuffling a deck of cards. The third approach is used when creating a GUID, which is basically a random 128 bit value.
You could use the Random class and a HashSet which will guarantee no duplicate items.
The HashSet class provides high-performance set operations. A set is a collection that contains no duplicate elements, and whose elements are in no particular order.
E.g:
HashSet<int> t = new HashSet<int>();
Random r = new Random();
while(t.Count < 50)//or the desired length of 't'
{
t.Add(r.Next(0,1000));//adjust min/max as needed
}
foreach (int i in t)
{
Console.WriteLine(i);
}
Console.Read();
Will give you a collection of 50 guaranteed unique random integers.
Since the number of elements in the set is not a requirement for this question it seems irrelevant to even mention, though if this is a requirement you can simply modify the line t.Count < ? to get a set of a desired length.
You could use Guid.NewGuid() or new Random().Next()
Assuming that you want unique numbers in a limited range, one (simple but possibly inefficient) way to do it is to create a list of all possible values (say, 0-99). Then you use System.Random to pick a random between 0 and (number of elements in list - 1). Get that index from the list, output it and remove the element. If you repeat the process, that element can no longer be generated and the numbers will be unique until you've used all possible values.
Create one instance of Random class. Make sure it is one!
then use this code
private Random random = new Random();
random.Next();
I have a character array as shown below :
char[] pwdCharArray = "abcdefghijklmnopqrstuvwxyzABCDEFG" +
"HIJKLMNOPQRSTUVWXYZ0123456789`~!##$%^&*()-_=+[]{}\\|;:'\",<" +
".>/?".ToCharArray();
and from this char array, i want to generate a string of minimum length 7 and all the characters in the string should be from the above char array.
How to do this operation?
What's the maximum length? (You may want to parameterize the methods below to specify a minimum and maximum length.) Here's a simple way of doing it for exactly 7 characters:
Here's the C# version:
public string GeneratePassword(Random rng)
{
char[] chars = new char[7];
for (int i = 0; i < chars.Length; i++)
{
chars[i] = pwdCharArray[rng.Next(pwdCharArray.Length)];
}
return new string(chars);
}
Note that the Random instance should be passed in to avoid the common problem of creating many instances of Random. I have an article describing this problem and ways around it. In essence, you should use one instance of Random per thread - don't create a new instance every time you want to use one, and don't reuse the same instance across multiple threads.
In fact, for a genuine password which is guarding sensitive information, you probably shouldn't be using Random at all, but rather something like RNGCryptoServiceProvider (or less directly, the results of RandomNumberGenerator.Create()). This can be somewhat harder to use, but will give you much more secure random numbers.
In Java it would be pretty similar, but then I'd use SecureRandom (which is fortunately rather easier to use than its .NET counterpart). In this case, you can create a new instance each time:
public String generatePassword() {
char[] chars = new char[7];
SecureRandom rng = new SecureRandom();
for (int i = 0; i < chars.length; i++) {
chars[i] = pwdCharArray[nextInt(pwdCharArray.length)];
}
return new String(chars);
}
Generate 7 random numbers between 0 and yourArray.length -1.
Pick the corresponding char in the array and put it in your final String.
Here is the code with a StringBuilder:
StringBuilder sb = new StringBuilder();
Random random = new Randdom();
for(int i=0; i<7; i++) {
sb.append(pwdCharArray[random.nextInt(0, pwdCharArray.length -1)]);
}
return sb.toString();
(C# example)
Random rand = new Random();
char[] arr = new char[rand.Next(7,15)];
for(int i = 0 ; i < arr.Length ; i++) {
arr[i] = pwdCharArray[rand.Next(pwdCharArray.Length)];
}
string pwd = new string(arr);
Here is a solution in Java, with variable length of the word, and test of working:
import java.util.*;
public class RandomWord {
// Valid characters
private static String VALID_CHARACTERS = "abcdefghijklmnopqrstuvwxyzABCDEFG" +
"HIJKLMNOPQRSTUVWXYZ0123456789`~!##$%^&*()-_=+[]{}\\|;:'\",<.>/?";
// Minimal length thw word can have
private static int MIN_LENGTH = 7;
// Maximal length will be MIN_LENGTH + THRESHOLD - 1
private static int THRESHOLD = 10;
// Generate a random number generator.
// The time in millis is used as seed prevents the numbers to be always the same in same order
Random randomGenerator = new Random(System.currentTimeMillis());
public String generateWord () {
// Actual length of the word (from MIN_LENGTH to MIN_LENGTH + THRESHOLD - 1)
int length = MIN_LENGTH + randomGenerator.nextInt(THRESHOLD);
// Loop for every character
StringBuilder word = new StringBuilder();
for (int i = 0; i < length; i++) {
// Appends one more random char
word.append(VALID_CHARACTERS.charAt(randomGenerator.nextInt(VALID_CHARACTERS.length())));
}
// Returns the random word
return word.toString();
}
// Test the class
public static void main (String[] args) {
// Instantiates and tests the class
RandomWord randomWord = new RandomWord();
for (int i = 0; i < 30; i++) {
String word = randomWord.generateWord();
System.out.println(word + " (" + word.length() + ")");
}
}
}