This question already has answers here:
Random number generator only generating one random number
(15 answers)
C# Random does not work like a random
(4 answers)
Closed 3 years ago.
I have a problem with a random function.
I am trying to create a string with 10 random letters/numbers.
However when I run the function, I get the same string 10 times in a row. What does that depend on and how can I truly create a random string in this case?
void testfunction()
{
for (int i = 0; i < 10; i++)
{
String randomname = getRandomLetterNumbers(10);
listBox1.Items.Add(randomname);
}
}
public String getRandomLetterNumbers(int nrLetterNumbers)
{
String letters = "abcdefghijklmnopqrstuvwxyz0123456789";
Random random = new Random(); String str = ""; int rand = 0;
for (int i = 0; i < nrLetterNumbers; i++)
{
rand = random.Next(0, letters.Length);
str = str + letters.Substring(rand, 1);
}
return str;
}
You need to move the random instantiation at class level else you got the same randoms (see duplicates for explanation).
Also you don't need to call substring, you can use char indexer.
private Random random = new Random();
public String getRandomLetterNumbers(int nrLetterNumbers)
{
String letters = "abcdefghijklmnopqrstuvwxyz0123456789";
String str = "";
int rand = 0;
for ( int i = 0; i < nrLetterNumbers; i++ )
{
rand = random.Next(0, letters.Length);
str = str + letters[rand];
}
return str;
}
Result:
l7jvgw77rf
e8h6i6bg1q
2jz8alaf7q
2k1rh5byqo
esgcmdy0f5
sjmhvbilu4
v29bm4gzym
4nznljdwv7
xk9c8s7u6f
wzev2msf0s
If you plan to generate long strings several times you may use StringBuilder instead of string concatenation, that avoids the copy of strings items each time you add a char:
using System.Text;
private string letters = "abcdefghijklmnopqrstuvwxyz0123456789";
public string GetRandomLetterNumbers(int nrLetterNumbers)
{
var builder = new StringBuilder(nrLetterNumbers);
for ( int i = 0; i < nrLetterNumbers; i++ )
{
builder.Append(letters[random.Next(0, letters.Length)]);
}
return builder.ToString();
}
Related
I'm using C# and I need to generate a random 10 digit number. So far, I've only had luck finding examples indicating min maximum value. How would i go about generating a random number that is 10 digits, which can begin with 0, (initially, I was hoping for random.Next(1000000000,9999999999) but I doubt this is what I want).
My code looks like this right now:
[WebMethod]
public string GenerateNumber()
{
Random random = new Random();
return random.Next(?);
}
**Update ended up doing like so,
[WebMethod]
public string GenerateNumber()
{
Random random = new Random();
string r = "";
int i;
for (i = 1; i < 11; i++)
{
r += random.Next(0, 9).ToString();
}
return r;
}
Use this to create random digits with any specified length
public string RandomDigits(int length)
{
var random = new Random();
string s = string.Empty;
for (int i = 0; i < length; i++)
s = String.Concat(s, random.Next(10).ToString());
return s;
}
try (though not absolutely exact)
Random R = new Random();
return ((long)R.Next (0, 100000 ) * (long)R.Next (0, 100000 )).ToString ().PadLeft (10, '0');
To get the any digit number without any loop, use Random.Next with the appropriate limits [100...00, 9999...99].
private static readonly Random _rdm = new Random();
private string PinGenerator(int digits)
{
if (digits <= 1) return "";
var _min = (int)Math.Pow(10, digits - 1);
var _max = (int)Math.Pow(10, digits) - 1;
return _rdm.Next(_min, _max).ToString();
}
This function calculated the lower and the upper bounds of the nth digits number.
To generate the 10 digit number use it like this:
PinGenerator(10)
If you want ten digits but you allow beginning with a 0 then it sounds like you want to generate a string, not a long integer.
Generate a 10-character string in which each character is randomly selected from '0'..'9'.
private void button1_Click(object sender, EventArgs e)
{
Random rand = new Random();
long randnum2 = (long)(rand.NextDouble() * 9000000000) + 1000000000;
MessageBox.Show(randnum2.ToString());
}
I came up with this method because I dont want to use the Random method :
public static string generate_Digits(int length)
{
var rndDigits = new System.Text.StringBuilder().Insert(0, "0123456789", length).ToString().ToCharArray();
return string.Join("", rndDigits.OrderBy(o => Guid.NewGuid()).Take(length));
}
hope this helps.
// ten digits
public string CreateRandomNumber
{
get
{
//returns 10 digit random number (Ticks returns 16 digit unique number, substring it to 10)
return DateTime.UtcNow.Ticks.ToString().Substring(8);
}
}
(1000000000,9999999999) is not random - you're mandating that it cannot begin with a 1, so you've already cut your target base by 10%.
Random is a double, so if you want a integer, multiply it by 1,000,000,000, then drop the figures after the decimal place.
private static Random random = new Random((int)DateTime.Now.Ticks);//thanks to McAden
public long LongBetween(long maxValue, long minValue)
{
return (long)Math.Round(random.NextDouble() * (maxValue - minValue - 1)) + minValue;
}
I tried to write a fast one:
private int GetNDigitsRandomNumber(int digits)
{
var min = 1;
for (int i = 0; i < digits-1; i++)
{
min *= 10;
}
var max = min * 10;
return _rnd.Next(min, max);
}
Here is a simple solution using format string:
string r = $"{random.Next(100000):00000}{random.Next(100000):00000}";
Random 10 digit number (with possible leading zeros) is produced as union of two random 5 digit numbers. Format string "00000" means leading zeros will be appended if number is shorter than 5 digits (e.g. 1 will be formatted as "00001").
For more about the "0" custom format specifier please see the documentation.
Random random = new Random();
string randomNumber = string.Join(string.Empty, Enumerable.Range(0, 10).Select(number => random.Next(0, 9).ToString()));
To generate a random 10 digit number in C#
Random RndNum = new Random();
int RnNum = RndNum.Next(1000000000,9999999999);
This question already has answers here:
Best way to repeat a character in C#
(21 answers)
Closed 5 years ago.
Hi im trying to make it so I can generate a random number 1-35 so for example if the number is 25 it will write out in a string 25 equal signs. How can I do that?
Random r = new Random();
r.next(1, 35);
R's result = 25
string result = 25 equal signs
Class string has a constructor that can do the work for you.
Random r = new Random();
int number = r.next(1, 35);
string result = new string('=', number);
Note also that it should be r.Next() not r.next().
Random r = new Random();
int occurrences = r.Next(1, 35);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < occurrences; i++)
{
sb.Append('=');
}
string output = sb.ToString();
Console.WriteLine(output);
You need a loop to repeat adding = to your result.
Update your code to
Random r = new Random();
int total = r.next(1, 35);
string result = "";
for (int i = 0; i < total; i++)
{
result += "=";
}
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I have the following code:
static void Main(string[] args)
{
int[] array = FillArray(); //Imagine FillArray() Fills the array with numbers from 0 to 100
string numbers = "";
for(int i = 0;i<array.Count();i++)
{
numbers += i.ToString();
}
}
What Im trying to do is to make this code more performant, maybe instead of using a For use a built in C# Method, extension method that makes this without having to repeat this For 100 times.
Edit: It is a broad Question, Of course you will have your own answer in regards of your knowledge we could say that all the answers that beat the timer of this Algorithm is sufficient answer for the question in itself.
Imagine to iterate with this algorithm 1.000.000.000 times, then we can compare with concrete numbers about different solutions.
Use StringBuilder if you want to concatenate string many many times.
Also use array.Length instead.
static void Main(string[] args)
{
int[] array = FillArray(); //Imagine FillArray() Fills the array with numbers from 0 to 100
var sb = new StringBuilder();
var len = array.Length;
for(int i = 0; i < len; i++)
{
sb.Append(i.ToString());
}
var numbers = sb.ToString();
}
To become really fast you need to get rid of (nearly) all allocations. Most people are not aware that i.ToString() allocates a new string instance which is not needed anymore after it has been appended to the StringBuilder instance.
Your initial version did concat the "temp" string with every i.ToString() which results in a string which gradually becomes larger and larger and hence slower to allocate every time a new slightly larger string. That is not an issue for a few strings but if you concat this way thousands or millions of strings it looks like this method will never terminate.
A much better approach is to use StringBuilder which is basically a mutable string that can extend its existing buffer. That allows efficient appending of strings without creating new temporary strings because string instances are not mutable. Now you are already quite good you can do better by allocating a large enough char array for all expected integers. Then you do not i.ToString() but i.ToCharArray() into the final char buffer. That beats the StringBuilder approach by over a factor 2.
ArrayToStringSteakOverCooked 0.39s 0.40s 0.43s
ArrayToStringKeithNicolasAlternate2 0.43s 0.44s 0.46s
ArrayToStringAlois 0.17s 0.16s 0.16s
The numbers above were achieved with this code
int[] Integers = Enumerable.Range(-5, 5 * 1000 * 1000).ToArray();
void ArrayToStringAlois()
{
char[] buffer = new char[Integers.Length * 11]; // an integer can have 10 digits plus sign = 11 digits. This buffer is big enough for all possible numbers
int startIdx = 0;
for (int i = 0; i < Integers.Length; i++)
{
startIdx += ToCharArray(Integers[i], buffer, startIdx);
}
string lret = new string(buffer, 0, startIdx);
GC.KeepAlive(lret);
}
public static int ToCharArray(int value, char[] buffer, int bufferIndex)
{
if (value == 0)
{
buffer[bufferIndex] = '0';
return 1;
}
int len = 1;
int upperBound = 0;
if (value < 0)
{
buffer[bufferIndex] = '-';
len = 2;
upperBound = 1;
}
value = Math.Abs(value);
for (int rem = value / 10; rem > 0; rem /= 10)
{
len++;
}
for (int i = len - 1; i >= upperBound; i--)
{
buffer[bufferIndex + i] = (char)('0' + (value % 10));
value /= 10;
}
return len;
}
void ArrayToStringSteakOverCooked()
{
var numbers = new StringBuilder();
var length = Integers.Length;
for (int i = 0; i < length; i++)
{
numbers.Append(i.ToString());
}
var lret = numbers.ToString();
GC.KeepAlive(lret);
}
void ArrayToStringKeithNicolasAlternate2()
{
var lret = string.Concat(Integers);
GC.KeepAlive(lret);
}
Try string.Concat which is specially designed for this:
static void Main(string[] args) {
string numbers = string.Concat(FillArray());
...
}
There are multiple different ways that get better performance. In my testing StringBuilder possibly has the slight edge (timing is variable across multiple runs and the numbers are very close, over 10 iterations StringBuilder was always the fastest, the other two kept swapping around on which was faster)
static void Orginal(int[] array)
{
string numbers = "";
for (int i = 0; i < array.Count(); i++)
{
numbers += i.ToString();
}
}
static void Improved(int[] array)
{
var numbers = new StringBuilder();
for (int i = 0; i < array.Length; i++)
{
numbers.Append(i);
}
}
static void Alternate(int[] array)
{
var strings = array.Select(n => n.ToString()).ToArray();
var s = string.Join("", strings);
}
static void Alternate2(int[] array)
{
string.Concat(array);
}
static void Time(string name, Action<int[]> action, int[] array)
{
Stopwatch stopwatch = Stopwatch.StartNew();
action(array);
stopwatch.Stop();
Console.WriteLine("{0} - {1}", name, stopwatch.ElapsedMilliseconds);
}
static void Main(string[] args)
{
var array = Enumerable.Range(0, 100000).ToArray();
for (int i = 0; i < 10; i++)
{
Time("Original", Orginal, array);
Time("Improved", Improved, array);
Time("Alternate", Alternate, array);
Time("Alternate2", Alternate2, array);
}
}
This question already has answers here:
Most efficient way to randomly "sort" (Shuffle) a list of integers in C#
(13 answers)
Closed 8 years ago.
I'm trying to create a console application for basic banking functions. I understand how the random number generator works, but I need to set up an array so that the random numbers don't repeat, considering that the random number that is generated represents the users personalized PIN number. How would I implement this into my current code?
class BankAccount
{
private string firstName;
private string lastName;
private int accountNumber;
private decimal balance;
static public int customers = 0;
private int pinNumber;
public decimal Balance
{
get
{
return balance;
}
set
{
if (value >= 0)
balance = value;
else
{
Console.WriteLine("There will be an overdraft fee of $10.00.");
balance = value - 10;
}
}
}
public string FirstName
{
get
{
return firstName;
}
}
public string LastName
{
get
{
return lastName;
}
}
public int AccountNumber
{
get
{
return accountNumber;
}
}
public int PinNumber
{
get
{
return pinNumber;
}
}
public BankAccount(string firstNameValue, string lastNameValue)
{
firstName = firstNameValue;
lastName = lastNameValue;
accountNumber = customers + 1;
Random pin = new Random();
pinNumber = pin.Next(1111, 9999);
Balance = 0;
customers++;
}
public BankAccount()
{
Balance = 0;
customers++;
}
public void Credit(decimal amount)
{
Balance = Balance + amount;
}
public void Debit(decimal amount)
{
if (amount > Balance)
Console.WriteLine("Debit amount exceeded account balance.");
Balance = Balance - amount;
}
public static decimal AverageBalance(BankAccount[] accounts)
{
int count = 0;
decimal total = 0;
for (int i = 0; i < accounts.Length; i++)
{
if (accounts[i] != null)
{
total += accounts[i].Balance;
count++;
}
}
return total / count;
}
}
When you do new Random(), .Net uses the current time as seed. If you do this more than once in a short span of time, you'll generate the same string of random numbers. You might want to just make a static Random variable in BankAccount.
static Random random = new Random();
// later, in the constructor
pinNumber = random.Next(0, 10000); // 0 <= pinNumber < 10000
I changed the range on Next so that it will generate in the full range.
This method initializes an array with distinct random numbers. I didn't test it but it should work.
Create an array, initialize it using the code below and then pass it to your method.
public void SetValues(int[] array)
{
Random randomNumber = new Random();
for (int i = 0; i < array.Length; i++)
{
bool distinctNumber = true;
int number = randomNumber.Next(1, 100);
for (int j = 0; j < i; j++)
{
if (number == array[j])
{
distinctNumber = false;
break;
}
}
if ( distinctNumber )
array[i] = number;
else
--i;
}
}
While I do not understand the concern about repeating digits in a PIN number, the solution should be pretty straight forward. Your array will only contain very few (four) digits, so there is no problem in checking if a number is repeated. The simplest way would be to use the Contains method and only append if the number is unique. Contains will however look at all numbers in the array, so you should either initialize it to something you do not allow (negative values), or build it using a list.
Random rnd = new Random();
var pin = new[] {-1, -1, -1, -1};
for(var i = 0; i < pin.length; i++)
int nextDigit = rnd.Next(0, 10);
while (pin.contains(nextDigit)){ nextDigit + rnd.Next(0, 10); }
pin[i] = nextDigit;
}
By borrowing an extension method from this excellent answer based on the Fisher-Yates shuffle this can be accomplished relatively cleanly.
First define an extension method to shuffle a given List<T>:
public static void Shuffle<T>(this IList<T> list)
{
Random rng = new Random();
int n = list.Count;
while (n > 1) {
n--;
int k = rng.Next(n + 1);
T value = list[k];
list[k] = list[n];
list[n] = value;
}
}
Then define the function to generate a PIN consisting of distinct digits:
public IEnumerable GeneratePIN() {
var pinDigits = new List<int>(Enumerable.Range(0,10));
pinDigits.Shuffle();
return pinDigits.Take(4);
}
Or, as an even better option, you can also use a more generalized pin generation function to generate pins of arbitrary lengths from arbitrary types.
public static IEnumerable<T> GeneratePIN<T>(IEnumerable<T> valueRange, int length)
{
var pinValues = new List<T>(valueRange);
pinValues.Shuffle();
return pinValues.Take(length);
}
That said, it's worth mentioning that restricting the PINs to distinct values reduces to number of possible PINs from 10000 to 5040, making it significantly less secure.
I've been playing around / researching ways to randomize the order of chars in a string. I frankly just don't understand how to do it. I've searched through the C# documentation and a handful of websites. I found one particular way of randomizing the order of chars in a string but I don't understand how it works. I've also read that the Random class isn't truly random, which would explain why the results are so similar.
How exactly does the current method I'm using function (especially the OrderBy() method).
Is there a better way to do this?
Current code
string baseList = "abcdefghijklmnopqrstuvwxyz";
Random random = new Random();
string[] randLists = new string[baseList.Length];
for (int i = 0; i < baseList.Length; i++)
{
randLists[i] = new string(baseList.ToCharArray().OrderBy(s => (random.Next(2) % 2) == 0).ToArray());
Console.WriteLine(randLists[i]);
}
Console.Read();
This is my attempt at randomizing but it doesn't function at all:
*string bL = "abcdefghijklmnopqrstuvwxyz";
string[] rL = new string[bL.Length];
Random randomizer = new Random();
for (int i = 0; i < bL.Length; i++)
{
rL = new string(bL.ToCharArray().OrderBy(c => (randomizer.Next(0, 25)).ToString()));
}*
Thanks in advance for any assistance. I'll continue researching in the meantime.
Although the code that you found is short, it does not make a nicely distributed shuffle of the original string: the randomizer is likely to give you the same numbers in the process of generating a shuffle, increasing a probability that the corresponding characters would remain in the same order relative to each other as in your original string.
One solution to this problem is using Fisher–Yates shuffle. It is easy to implement (you need to stay away from common implementation errors, though).
Since string is immutable, you would need to shuffle an array of characters, and then make a string from it.
To add to the suggestion of the Fisher-Yates shuffle, here's a code sample, just ignore the test assertion, just trying to debug and make sure it's random enough.
[TestMethod]
public void RandomizeText()
{
string baseList = "abcdefghijklmnopqrstuvwxyz";
char[] result = baseList.ToCharArray();
Shuffle<char>(result);
var final = string.Join("", result);
final.Should().NotMatch(baseList);
}
public void Shuffle<T>(T[] array)
{
var random = new Random();
for (int x = 0; x < 100; x++)
{
for (int i = array.Length; i > 1; i--)
{
// Pick random element to swap.
int j = random.Next(i); // 0 <= j <= i-1
// Swap.
T tmp = array[j];
array[j] = array[i - 1];
array[i - 1] = tmp;
}
}
}
Another example...
static void Main(string[] args)
{
string baseList = "abcdefghijklmnopqrstuvwxyz";
Console.WriteLine(baseList);
string shuffled = Shuffle(baseList);
Console.WriteLine(shuffled);
Console.ReadLine();
}
static Random R = new Random();
static string Shuffle(string list)
{
int index;
List<char> chars = new List<char>(list);
StringBuilder sb = new StringBuilder();
while (chars.Count > 0)
{
index = R.Next(chars.Count);
sb.Append(chars[index]);
chars.RemoveAt(index);
}
return sb.ToString();
}