답변:
이 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
: 임의성을 보다 견고하게 만들기위한 몇 가지 좋은 "향상된 기능"이 있습니다. 임의성 .
질문은 매우 단순 해 보이지만 대답은 약간 복잡합니다. 거의 모든 사람들이 Random 클래스를 사용하도록 제안했으며 일부는 RNG 암호화 클래스를 사용하도록 제안했습니다. 그러나 언제 무엇을 선택할 지.
이를 위해서는 먼저 RANDOMNESS라는 용어와 그 뒤에있는 철학을 이해해야합니다.
C # https://www.youtube.com/watch?v=tCYxc-2-3fY를 사용하여 RANDOMNESS의 철학에 깊이 들어가는이 비디오를 시청 하시기 바랍니다.
우선 RANDOMNESS의 철학을 이해하겠습니다. 우리가 사람에게 RED, GREEN, YELLOW 중에서 내부에서 일어나는 일을 선택하라고 말할 때. 사람이 빨간색, 노란색 또는 녹색을 선택하게하는 이유는 무엇입니까?
일부 초기 생각은 사람의 마음에 들어가 그의 선택을 결정합니다. 좋아하는 색, 행운의 색 등이 될 수 있습니다. 다시 말해 RANDOM에서 SEED라고하는 초기 트리거입니다.이 SEED는 시작점이며, RANDOM 값을 선택하도록하는 트리거입니다.
이제 SEED가 추측하기 쉬운 경우 이러한 종류의 난수를 PSEUDO 라고 하며 시드를 추측하기 어려운 경우 해당 난수를 SECURED 난수 라고 합니다.
예를 들어 날씨와 소리의 조합에 따라 색상을 선택하면 초기 씨앗을 추측하기가 어렵습니다.
이제 중요한 진술을하겠습니다 :-
*“랜덤”클래스는 PSEUDO 난수 만 생성하며 SECURE 난수를 생성하려면“RNGCryptoServiceProvider”클래스를 사용해야합니다.
랜덤 클래스는 CPU 클럭에서 시드 값을 가져와 매우 예측 가능합니다. 즉, C #의 RANDOM 클래스는 의사 난수를 생성합니다. 아래는 동일한 코드입니다.
** 참고 : ** .NET Core 2.0.0+
는 매개 변수없는 생성자에서 다른 시드를 사용합니다 Guid.NewGuid().GetHashCode()
. CPU 클럭 대신을 사용합니다 .
var random = new Random();
int randomnumber = random.Next()
그동안 RNGCryptoServiceProvider
클래스가 사용하는 OS는 씨앗을 생성하기 위해 엔트로피. OS 엔트로피는 소리, 마우스 클릭 및 키보드 타이밍, 열 온도 등을 사용하여 생성되는 임의의 값입니다. 아래는 동일한 코드입니다.
using (RNGCryptoServiceProvider rg = new RNGCryptoServiceProvider())
{
byte[] rno = new byte[5];
rg.GetBytes(rno);
int randomvalue = BitConverter.ToInt32(rno, 0);
}
OS 엔트로피를 이해하려면 14:30 https://www.youtube.com/watch?v=tCYxc-2-3fY 에서이 비디오를 참조하십시오. 여기서 OS 엔트로피의 논리가 설명됩니다. 따라서 간단한 단어로 RNG Crypto를 사용하면 안전한 임의의 숫자가 생성됩니다.
RandomNumberGenerator.Create()
생성자를 호출하는 대신 사용 하는 것이 좋습니다 RNGCryptoServiceProvider
.
새로운 Random () 할 때마다 초기화됩니다. 이것은 타이트한 루프에서 동일한 값을 여러 번 얻는다는 것을 의미합니다. 단일 임의 인스턴스를 유지하고 동일한 인스턴스에서 다음을 계속 사용해야합니다.
//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
객체 를 저장하려고했습니다 . 두 경우 모두 동일한 난수를 얻었습니다. Pankaj의 접근 방식으로는 발생하지 않았습니다. 아마도 이것은 임의적 이지만 지금은 의심 스럽습니다. 다른 스레드에서 동일한 초에 임의의 숫자를 쿼리하고 있습니다.
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);
}
Jon Skeet의 StaticRandom 메소드를 의사 난수로 작성한 MiscUtil 클래스 라이브러리에서 사용할 수 있습니다.
using MiscUtil;
...
for (int i = 0; i < 100;
Console.WriteLine(StaticRandom.Next());
COBOL 답변을 제외한 모든 솔루션을 시도했습니다 ... lol
이 솔루션들 중 어느 것도 충분하지 않았습니다. int 루프를 위해 fast에서 randoms가 필요했으며 매우 넓은 범위에서도 수많은 중복 값을 얻었습니다. 너무 오랫동안 임의의 결과에 정착 한 후 마침내이 문제를 한 번에 해결하기로 결정했습니다.
씨앗에 관한 모든 것입니다.
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 #의 암호화 클래스를 사용하여 생성 할 수있는 "secure pseudo random generator"가 가장 가깝습니다 RNGCryptoServiceProvider
.
그럼에도 불구하고 여전히 실제 난수가 필요한 경우 방사성 붕괴를 설명하는 장치와 같은 외부 소스를 난수 생성기의 시드로 사용해야합니다. 정의상 순전히 알고리즘적인 수단으로 생성 된 숫자는 실제로 임의의 숫자 일 수 없습니다.
랜덤 오브젝트를 생성
Random rand = new Random();
그리고 그것을 사용하십시오
int randomNumber = rand.Next(min, max);
new Random()
임의의 숫자가 필요할 때마다 초기화 할 필요가 없으며 임의의 숫자를 시작한 다음 루프 내에서 필요한 횟수만큼 사용하십시오.
new Random()
현재 진드기를 시드로 사용합니다. 동일한 밀리 초 내에 여러 인스턴스를 인스턴스화하면 (틱이 아닌) 동일한 값이 반환됩니다.
여기 에서 수정 된 답변입니다 .
Intel Secure Key 호환 CPU에 액세스 할 수있는 경우 https://github.com/JebteK/RdRand 및 https://www.rdrand.com/ 라이브러리를 사용하여 실제 난수 및 문자열을 생성 할 수 있습니다.
여기 에서 최신 버전을 다운로드하고 Jebtek.RdRand를 포함하고 using 문을 추가하십시오. 그런 다음이 작업 만하면됩니다.
// 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();
코드를 실행할 호환 CPU가없는 경우 rdrand.com에서 RESTful 서비스를 사용하십시오. 프로젝트에 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()
대부분의 시간에 한계 (최소 및 최대 mumbers)를 제어하려고합니다. 따라서 임의의 숫자가 시작하고 끝나는 위치를 지정해야합니다.
이 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; }
}
당신은 두 개의 다른 ID를 얻을 것이라고 생각하십니까? 아니
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를 사용합니다.
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 년이라는 것을 알고 있지만이 질문은 오래되었지만 매력이 있기 때문에 변경 사항을 문서화하는 것이 좋습니다.
내가 잠시 전에 만든이 질문을 언급 할 수 있습니다.
Microsoft는 임의의 기본 시드를 변경 했습니까?
기본적으로 기본 시드가에서 (으) Environment.TickCount
로 변경되었습니다. Guid.NewGuid().GetHashCode()
따라서 임의의 인스턴스 2 개를 생성하면 동일한 숫자가 표시되지 않습니다.
https://github.com/dotnet/coreclr/pull/2192/commits/9f6a0b675e5ac0065a268554de49162c539ff66d 에서 .NET Framework / .NET Core (2.0.0+)의 파일 차이를 확인할 수 있습니다.
RNGCryptoServiceProvider만큼 안전하지는 않지만 적어도 이상한 결과를 제공하지는 않습니다.
Interop.GetRandomBytes((byte*)&result, sizeof(int));
입니다.
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);
}
}
아래처럼 균일하게 분포 된 난수 생성기를 원한다고 가정합니다. C # 및 C ++를 포함한 대부분의 프로그래밍 언어에서 난수는 사용하기 전에 제대로 섞이지 않습니다. 이것은 당신이 같은 숫자를 반복해서 얻을 것이라는 것을 의미합니다. 이것은 실제로 무작위가 아닙니다. 같은 숫자를 반복해서 그리는 것을 피하려면 씨앗이 필요합니다. 일반적으로 시간의 틱은이 작업에 적합합니다. 매번 같은 시드를 사용하는 경우 같은 숫자를 계속해서 얻게됩니다. 따라서 항상 다양한 씨앗을 사용하십시오. 씨앗은 항상 변화하기 때문에 시간은 씨앗의 좋은 소스입니다.
int GetRandomNumber(int min, int max)
{
Random rand = new Random((int)DateTime.Now.Ticks);
return rand.Next(min, max);
}
정규 분포의 난수 생성기를 찾고 있다면 Box-Muller 변환을 사용할 수 있습니다. Random Gaussian Variable Question에서 yoyoyoyosef의 답변을 확인하십시오. 정수를 원하기 때문에 마지막에 double 값을 정수로 캐스트해야합니다.
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();
}
}