Відповіді:
Random
Клас використовується для створення випадкових чисел. (Псевдовипадковий, що, звичайно.).
Приклад:
Random rnd = new Random();
int month = rnd.Next(1, 13); // creates a number between 1 and 12
int dice = rnd.Next(1, 7); // creates a number between 1 and 6
int card = rnd.Next(52); // creates a number between 0 and 51
Якщо ви збираєтеся створити більше одного випадкового числа, вам слід зберегти Random
екземпляр і повторно використовувати його. Якщо ви створюєте нові екземпляри занадто близько за часом, вони створюватимуть ті ж серії випадкових чисел, що і випадковий генератор виводиться із системних годин.
rnd
як static
та / або встановити його лише один раз при ініціалізації коду.
Random
...
Random
, щоб зробити вашу випадковість більш надійною: ericlippert.com/2019/02/04/fixing-random-part-2 та codeblog.jonskeet.uk/2009/11/04/revisiting -випадковість .
Питання виглядає дуже просто, але відповідь трохи складний. Якщо ви бачите, майже кожен запропонував використовувати клас Random, а деякі запропонували використовувати крипто-клас RNG. Але тоді, коли вибрати, що.
Для цього нам потрібно спершу розібратися в терміні РАННІСТЬ та філософії, що стоїть за ним.
Я б закликав вас переглянути це відео, яке заглиблюється у філософію RANDOMNESS, використовуючи C # https://www.youtube.com/watch?v=tCYxc-2-3fY
Перш за все, давайте розберемося з філософією РАДОННОСТІ. Коли ми говоримо людині вибирати між ЧЕРВОНОЮ, ЗЕЛЕНОЮ та ЖОВТОЮ, що відбувається всередині. Що змушує людину обирати ЧЕРВНУ або ЖОВТУ або ЗЕЛЕНУ?
Деякі початкові думки впадають у розум людей, який вирішує його вибір, це може бути улюблений колір, вдалий колір тощо. Іншими словами, деякий початковий тригер, який ми називаємо в RANDOM як SEED.The SEED - це початкова точка, тригер, який підштовхує його до вибору значення RANDOM.
Тепер, якщо SEED легко здогадатися, то такі види випадкових чисел називаються PSEUDO, а коли насіння важко здогадатися, ці випадкові числа називаються ЗАБЕЗПЕЧЕННЯМИ випадкові числа.
Наприклад, людина вибирає колір залежно від погоди та звукової комбінації, тоді було б важко здогадатися про початкове насіння.
Тепер дозвольте зробити важливу заяву: -
* Клас "Random" генерує лише випадкове число PSEUDO, а для створення безпечного випадкового числа нам потрібно використовувати клас "RNGCryptoServiceProvider".
Випадковий клас приймає значення насіннєвих процесорних годин, що дуже передбачувано. Так іншими словами, клас RANDOM C # породжує псевдовипадкові числа, нижче - код для тих же.
** Примітка: ** .NET Core 2.0.0+
використовує інше насіннєве значення в конструкторі без параметрів: замість тактового процесора він використовує Guid.NewGuid().GetHashCode()
.
var random = new Random();
int randomnumber = random.Next()
У той час як RNGCryptoServiceProvider
клас використовує ентропію ОС для генерації насіння. Ентропія ОС - випадкове значення, яке генерується за допомогою звуку, натискання миші та таймінгів клавіатури, теплової температури тощо. Нижче йде код для того ж.
using (RNGCryptoServiceProvider rg = new RNGCryptoServiceProvider())
{
byte[] rno = new byte[5];
rg.GetBytes(rno);
int randomvalue = BitConverter.ToInt32(rno, 0);
}
Щоб зрозуміти ентропію ОС, дивіться це відео з 14:30 https://www.youtube.com/watch?v=tCYxc-2-3fY, де пояснюється логіка ентропії ОС. Таким чином, прості слова RNG Crypto генерують БЕЗКОШТОВНІ випадкові числа.
RandomNumberGenerator.Create()
замість виклику конструктора, RNGCryptoServiceProvider
оскільки він доступний не на всіх платформах.
Кожен раз, коли ви робите новий Random (), він ініціалізується. Це означає, що в тісному циклі ви отримуєте однакове значення багато разів. Ви повинні зберігати один випадковий екземпляр і продовжувати використовувати Next у тому ж екземплярі.
//Function to get random number
private static readonly Random getrandom = new Random();
public static int GetRandomNumber(int min, int max)
{
lock(getrandom) // synchronize
{
return getrandom.Next(min, max);
}
}
Random
об’єкт. В обох випадках я отримав однакове випадкове число. З підходом з Панкая цього не сталося. Можливо, це випадково , але я сумніваюся зараз. Я запитую випадкове число за одну і ту ж секунду з різних потоків.
Остерігайтеся того, що new Random()
посіяно на поточну мітку часу.
Якщо ви хочете генерувати лише одне число, ви можете використовувати:
new Random().Next( int.MinValue, int.MaxValue )
Для отримання додаткової інформації подивіться клас Random , хоча зверніть увагу:
Однак, оскільки годинник має кінцеву роздільну здатність, використовуючи конструктор без параметрів для створення різних випадкових об'єктів у близькій послідовності створює генератори випадкових чисел, які виробляють однакові послідовності випадкових чисел
Тому не використовуйте цей код для створення серії випадкових чисел.
new Random()
в циклі важливий момент.
Я хотів додати криптографічно захищену версію:
Клас RNGCryptoServiceProvider ( MSDN або dotnetperls )
Він реалізує IDisposable.
using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider())
{
byte[] randomNumber = new byte[4];//4 for int32
rng.GetBytes(randomNumber);
int value = BitConverter.ToInt32(randomNumber, 0);
}
Ви можете використовувати метод StaticRandom Джона Скета в бібліотеці класів MiscUtil, яку він створив для псевдовипадкового числа.
using MiscUtil;
...
for (int i = 0; i < 100;
Console.WriteLine(StaticRandom.Next());
Я спробував усі ці рішення, за винятком відповіді COBOL ... lol
Жодне з цих рішень було недостатньо хорошим. Мені були потрібні рандеми в швидкому для циклу int, і я отримував тонни повторюваних значень навіть у дуже широких межах. Занадто довго погодившись із випадковими результатами, я вирішив остаточно вирішити цю проблему раз і назавжди.
Вся справа в насінні.
Я створюю випадкове ціле число, розбираючи нецифрові знаки з Guid, а потім використовую це для інстанціювання мого класу Random.
public int GenerateRandom(int min, int max)
{
var seed = Convert.ToInt32(Regex.Match(Guid.NewGuid().ToString(), @"\d+").Value);
return new Random(seed).Next(min, max);
}
Оновлення : висівання не потрібне, якщо інстанціювати клас Random один раз. Тож було б найкраще створити статичний клас і відкликати метод від цього.
public static class IntUtil
{
private static Random random;
private static void Init()
{
if (random == null) random = new Random();
}
public static int Random(int min, int max)
{
Init();
return random.Next(min, max);
}
}
Тоді ви можете використовувати статичний клас на зразок цього ..
for(var i = 0; i < 1000; i++)
{
int randomNumber = IntUtil.Random(1,100);
Console.WriteLine(randomNumber);
}
Зізнаюся, мені більше подобається такий підхід.
Числа, згенеровані вбудованим Random
класом (System.Random), генерують псевдовипадкові числа.
Якщо ви хочете істинних випадкових чисел, найближчим до нас може стати "безпечний генератор псевдовипадкових випадків", який можна створити за допомогою криптографічних класів у C #, таких як RNGCryptoServiceProvider
.
Незважаючи на це, якщо вам все-таки потрібні справжні випадкові числа, вам потрібно буде використовувати зовнішнє джерело, наприклад пристрої обліку радіоактивного розпаду як насіння для генератора випадкових чисел. Оскільки, за визначенням, будь-яке число, породжене суто алгоритмічними засобами, не може бути справді випадковим.
створити об'єкт Random
Random rand = new Random();
і використовувати його
int randomNumber = rand.Next(min, max);
вам не доведеться ініціалізувати new Random()
кожен раз, коли вам потрібно випадкове число, ініціюйте одне випадкове, а потім використовуйте його стільки разів, скільки вам потрібно в циклі або будь-якому іншому
new Random()
використовує поточні кліщі як насіння. Коли ви інстанціюєте кілька екземплярів протягом однієї мілісекунди (на відміну від галочки), ви отримаєте те саме значення, яке повертається.
Модифікована відповідь звідси .
Якщо у вас є доступ до сумісного процесора Intel Secure Key, ви можете генерувати реальні випадкові числа та рядки за допомогою цих бібліотек: https://github.com/JebteK/RdRand та https://www.rdrand.com/
Просто завантажте останню версію звідси , включіть Jebtek.RdRand і додайте для цього заяву. Тоді все, що вам потрібно зробити, це:
// Check to see if this is a compatible CPU
bool isAvailable = RdRandom.GeneratorAvailable();
// Generate 10 random characters
string key = RdRandom.GenerateKey(10);
// Generate 64 random characters, useful for API keys
string apiKey = RdRandom.GenerateAPIKey();
// Generate an array of 10 random bytes
byte[] b = RdRandom.GenerateBytes(10);
// Generate a random unsigned int
uint i = RdRandom.GenerateUnsignedInt();
Якщо у вас немає сумісного процесора для виконання коду, просто скористайтеся послугами RESTful на rdrand.com. З бібліотекою обгортки RdRandom, включеною у ваш проект, вам просто потрібно буде це зробити (ви отримуєте 1000 безкоштовних дзвінків під час реєстрації):
string ret = Randomizer.GenerateKey(<length>, "<key>");
uint ret = Randomizer.GenerateUInt("<key>");
byte[] ret = Randomizer.GenerateBytes(<length>, "<key>");
Хоча це нормально:
Random random = new Random();
int randomNumber = random.Next()
Ви хочете контролювати ліміт (мінімум та максимум), більшу частину часу. Тому потрібно вказати, де починається і закінчується випадкове число.
The Next()
Метод приймає два параметри, хв і макс.
Тож якщо я хочу, щоб моє випадкове число було між скажімо 5 і 15, я б просто зробив
int randomNumber = random.Next(5, 16)
Це клас, який я використовую. Діє якRandomNumber.GenerateRandom(1, 666)
internal static class RandomNumber
{
private static Random r = new Random();
private static object l = new object();
private static Random globalRandom = new Random();
[ThreadStatic]
private static Random localRandom;
public static int GenerateNewRandom(int min, int max)
{
return new Random().Next(min, max);
}
public static int GenerateLockedRandom(int min, int max)
{
int result;
lock (RandomNumber.l)
{
result = RandomNumber.r.Next(min, max);
}
return result;
}
public static int GenerateRandom(int min, int max)
{
Random random = RandomNumber.localRandom;
if (random == null)
{
int seed;
lock (RandomNumber.globalRandom)
{
seed = RandomNumber.globalRandom.Next();
}
random = (RandomNumber.localRandom = new Random(seed));
}
return random.Next(min, max);
}
}
Я хотів продемонструвати, що відбувається, коли кожен раз використовується новий випадковий генератор. Припустимо, у вас є два методи або два класи, кожен з яких вимагає випадкового числа. І наївно ти їх кодуєш так:
public class A
{
public A()
{
var rnd=new Random();
ID=rnd.Next();
}
public int ID { get; private set; }
}
public class B
{
public B()
{
var rnd=new Random();
ID=rnd.Next();
}
public int ID { get; private set; }
}
Як ви думаєте, ви отримаєте два різних посвідчення особи? НОПА
class Program
{
static void Main(string[] args)
{
A a=new A();
B b=new B();
int ida=a.ID, idb=b.ID;
// ida = 1452879101
// idb = 1452879101
}
}
Рішення полягає у тому, щоб завжди використовувати один статичний генератор випадкових випадків. Подобається це:
public static class Utils
{
public static readonly Random random=new Random();
}
public class A
{
public A()
{
ID=Utils.random.Next();
}
public int ID { get; private set; }
}
public class B
{
public B()
{
ID=Utils.random.Next();
}
public int ID { get; private set; }
}
RNGCryptoServiceProvider
краще все-таки зателефонувати.
Для сильного випадкового насіння я завжди використовую CryptoRNG, а не Time.
using System;
using System.Security.Cryptography;
public class Program
{
public static void Main()
{
var random = new Random(GetSeed());
Console.WriteLine(random.Next());
}
public static int GetSeed()
{
using (var rng = new RNGCryptoServiceProvider())
{
var intBytes = new byte[4];
rng.GetBytes(intBytes);
return BitConverter.ToInt32(intBytes, 0);
}
}
}
Random random = new Random ();
int randomNumber = random.Next (lowerBound,upperBound);
Так само як замітка для подальшої довідки.
Якщо ви використовуєте .NET Core, кілька випадкових випадків не такі небезпечні, як раніше. Я знаю, що це питання з 2010 року, але оскільки це питання є старим, але має певну привабливість, я думаю, що це добре, щоб задокументувати зміни.
Ви можете звернутися до цього питання, яке я заздалегідь запитав:
Майкрософт змінив випадкове насіння за замовчуванням?
В основному вони змінили насіння за замовчуванням з Environment.TickCount
наGuid.NewGuid().GetHashCode()
, тому якщо ви створите 2 екземпляри випадкових випадків, вони не відображатимуть однакові числа.
Тут ви бачите, що файл відрізняється від .NET Framework / .NET Core (2.0.0+) тут: https://github.com/dotnet/coreclr/pull/2192/commits/9f6a0b675e5ac0065a268554de49162c539ff66d
Це не так безпечно, як RNGCryptoServiceProvider, але принаймні це не дасть вам дивних результатів.
Interop.GetRandomBytes((byte*)&result, sizeof(int));
.
Числа, обчислені комп'ютером за допомогою детермінованого процесу, за визначенням не можуть бути випадковими.
Якщо ви хочете справжні випадкові числа, випадковість виникає від атмосферного шуму або радіоактивного розпаду.
Ви можете спробувати, наприклад, RANDOM.ORG (це знижує продуктивність)
Random rand = new Random();
int name = rand.Next()
Введіть будь-які значення, які ви хочете, у другі дужки, переконайтеся, що ви встановили ім'я, написавши опорний та подвійний вкладки для створення коду
Якщо ви хочете, щоб CSRNG генерував випадкові числа між хв і макс, це для вас. Це буде ініціалізувати Random
класи із захищеними випадковими насінням.
class SecureRandom : Random
{
public static byte[] GetBytes(ulong length)
{
RNGCryptoServiceProvider RNG = new RNGCryptoServiceProvider();
byte[] bytes = new byte[length];
RNG.GetBytes(bytes);
RNG.Dispose();
return bytes;
}
public SecureRandom() : base(BitConverter.ToInt32(GetBytes(4), 0))
{
}
public int GetRandomInt(int min, int max)
{
int treashold = max - min;
if(treashold != Math.Abs(treashold))
{
throw new ArithmeticException("The minimum value can't exceed the maximum value!");
}
if (treashold == 0)
{
throw new ArithmeticException("The minimum value can't be the same as the maximum value!");
}
return min + (Next() % treashold);
}
public static int GetRandomIntStatic(int min, int max)
{
int treashold = max - min;
if (treashold != Math.Abs(treashold))
{
throw new ArithmeticException("The minimum value can't exceed the maximum value!");
}
if(treashold == 0)
{
throw new ArithmeticException("The minimum value can't be the same as the maximum value!");
}
return min + (BitConverter.ToInt32(GetBytes(4), 0) % treashold);
}
}
На жаль, OP дійсно вимагає випадкового int
значення, але для простої мети поділитися знаннями, якщо ви хочете випадкове BigInteger
значення, ви можете використовувати наступне твердження:
BigInteger randomVal = BigInteger.Abs(BigInteger.Parse(Guid.NewGuid().ToString().Replace("-",""), NumberStyles.AllowHexSpecifier));
Я вважаю, що ви хочете рівномірно розподіленого генератора випадкових чисел, як показано нижче. Випадкове число у більшості мов програмування, включаючи C # та C ++, не використовується правильно. Це означає, що ви будете отримувати однакове число знову і знову, що насправді не є випадковим. Щоб не малювати однакове число знову і знову, вам потрібно насіння. Як правило, кліщі в часі добре для цього завдання. Пам’ятайте, що ви будете отримувати одне і те ж число, якщо ви будете використовувати одне і те ж насіння кожен раз. Тому намагайтеся завжди використовувати різні насіння. Час - гарне джерело для насіння, тому що вони завжди продаються.
int GetRandomNumber(int min, int max)
{
Random rand = new Random((int)DateTime.Now.Ticks);
return rand.Next(min, max);
}
якщо ви шукаєте генератор випадкових чисел для нормального розподілу, ви можете використовувати перетворення Box-Muller. Перевірте відповідь yoyoyoyosef у випадковому гауссовому змінному запитанні. Оскільки ви хочете ціле число, вам потрібно присвоїти подвійне значення цілому числу в кінці.
Random rand = new Random(); //reuse this if you are generating many
double u1 = 1.0-rand.NextDouble(); //uniform(0,1] random doubles
double u2 = 1.0-rand.NextDouble();
double randStdNormal = Math.Sqrt(-2.0 * Math.Log(u1)) *
Math.Sin(2.0 * Math.PI * u2); //random normal(0,1)
double randNormal =
mean + stdDev * randStdNormal; //random normal(mean,stdDev^2)
Найпростіший спосіб, мабуть, просто Random.range(1, 3)
Це створило б число від 1 до 2.
Ви можете спробувати з випадковим значенням насіння, скориставшись нижче:
var rnd = new Random(11111111); //note: seed value is 11111111
string randomDigits = rnd.Next();
var requestNumber = $"SD-{randomDigits}";
Чому б не використовувати int randomNumber = Random.Range(start_range, end_range)
?
Використовуйте один екземпляр Random кілька разів
// Somewhat better code...
Random rng = new Random();
for (int i = 0; i < 100; i++)
{
Console.WriteLine(GenerateDigit(rng));
}
...
static int GenerateDigit(Random rng)
{
// Assume there'd be more logic here really
return rng.Next(10);
}
У цій статті розглядається, чому випадковість спричиняє стільки проблем, і як їх вирішити. http://csharpindepth.com/Articles/Chapter12/Random.aspx
Random
не є безпечним для потоків класом. Якщо ви створюєте один екземпляр, вам слід обмежити доступ до нього за механізмом блокування.
Спробуйте виконати наступні прості дії для створення випадкових чисел:
Створити функцію:
private int randomnumber(int min, int max)
{
Random rnum = new Random();
return rnum.Next(min, max);
}
Використовуйте вищевказану функцію в місці, де ви хочете використовувати випадкові числа. Припустимо, ви хочете використовувати його в текстовому полі.
textBox1.Text = randomnumber(0, 999).ToString();
0 - хв, а 999 - макс. Ви можете змінити значення на все, що завгодно.
У мене завжди є методи, які генерують випадкові числа, які допомагають для різних цілей. Я сподіваюся, що це може допомогти і вам:
public class RandomGenerator
{
public int RandomNumber(int min, int max)
{
var random = new Random();
return random.Next(min, max);
}
public string RandomString(int size, bool lowerCase)
{
var builder = new StringBuilder();
var random = new Random();
char ch;
for (int i = 0; i < size; i++)
{
ch = Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65)));
builder.Append(ch);
}
if (lowerCase)
return builder.ToString().ToLower();
return builder.ToString();
}
}