System.Security.Cryptography.RandomNumberGenerator 대신 C # 클래스 System.Random을 사용하는 이유는 무엇입니까?


85

왜 누군가 System.Security.Cryptography.RandomNumberGenerator (또는 RandomNumberGenerator가 추상이기 때문에 하위 클래스) 의 암호화 보안 난수 생성기를 사용하는 대신 System.Random 의 "표준"난수 생성기를 사용하는 이유는 무엇입니까?

Nate Lawson은 Google Tech Talk 프레젠테이션 " Crypto Strikes Back "(13 분 11 초)에서 Python, Java 및 C #의 "표준"난수 생성기를 사용하지 말고 대신 암호화 보안 버전을 사용하라고 말합니다.

난수 생성기의 두 가지 버전의 차이점을 알고 있습니다 ( 질문 101337 참조 ).

그러나 보안 난수 생성기를 항상 사용하지 않는 이유는 무엇입니까? 왜 System.Random을 사용합니까? 아마도 성능?


7
어느 쪽을 입력 하시겠습니까?
Macha

13
너무 많은 사람들이 그것을 자신이하는 일에 대한 정당화로 심각하게 사용합니다 (보통 소리 내지 않음). 코드는 쓰여진 것보다 더 많이 읽혀집니다. 누가 사소한 길이 차이를 신경 쓰나요?
Mark Sowul

3
그러나 어쨌든 암호화를 수행하지 않는 경우 암호화 RNG를 사용해야하는 이유는 무엇입니까?
Mark Sowul

3
@Macha, 그의를 위해 무엇 별명 ->using R = System.Security.Cryptography.RandomNumberGenerator; R.Create();
cchamberlain

답변:


144

속도와 의도. 난수를 생성하고 보안이 필요하지 않은 경우 왜 느린 암호화 기능을 사용합니까? 보안이 필요하지 않은데 왜 다른 사람이 그 번호가 보안이되지 않을 때 보안을 위해 사용될 수 있다고 생각하게 만들까요?


30
나는 의도 논쟁을 매우 좋아합니다.
Lernkurve

12
Random.GetNext는 특히 스레드 환경에서 스펙트럼을 통해 난수를 "확산"하는 데는 전혀 도움이되지 않습니다. Rand5 문제에서 Rand7에 대한 다양한 솔루션을 테스트하는 프로그램을 작성할 때이 문제가 발생했습니다. 0에서 10 사이의 난수 100000 개에 대한 빠른 스레드 테스트에서 생성 된 숫자 중 82470 개는 0이었습니다. 이전 테스트에서 비슷한 불일치를 보았습니다. Crytpography random은 숫자 분포가 매우 균등합니다. 교훈은 항상 임의의 데이터를 테스트하여 귀하의 필요에 "충분히 임의적"인지 확인하는 것입니다.
Kristoffer L

35
@Kristoffer 나는 당신이 오용했다고 생각합니다 Random. 추측 해 보겠습니다. Random각 숫자에 대해 클래스 의 새 인스턴스를 만들었습니다. 이는 대략적인 타이머에 의해 시드되었으므로 약 1-16ms 간격 동안 동일한 값으로 시드됩니다.
CodesInChaos 2011-06-17

15
@CodesInChaos : 그 외에도 Random여러 스레드에서 동일한 객체를 사용할 때 모두 0을 반환 하는 경쟁 조건이 있습니다.
BlueRaja-Danny Pflughoeft 2010 년

3
@KristofferL은 다음을 참조하십시오 코멘트 위 항목 이 답변
대니 Pflughoeft - BlueRaja

65

속도와 더 유용한 인터페이스 외에도 NextDouble()고정 시드 값을 사용하여 반복 가능한 무작위 시퀀스를 만드는 것도 가능합니다. 이것은 테스팅 중에 매우 유용합니다.

Random gen1 = new Random();     // auto seeded by the clock
Random gen2 = new Random(0);    // Next(10) always yields 7,8,7,5,2,....

2
이해하기 쉬운 BitConverter.ToInt32 (Byte [] value, int startIndex)가 있습니다. ;)
sisve 2010 년

7
Ian Bell과 David Braben은 컴퓨터 게임 Elite에서 무작위 생성기를 사용하여 매우 제한된 메모리로 방대한 행성 및 그 속성 (크기 등) 목록을 만들었습니다. 이것은 또한 (시드에서) 결정 론적 패턴을 생성하는 생성기에 의존합니다-Crypto one은 분명히 제공하지 않습니다 (설계 상). 여기에 어떻게했는지에 대한 더 많은 정보가 있습니다 : wiki.alioth.net/index.php / Random_number_generator 및 책 "무한 게임 세계 : 수학적 기술"ISBN : 1584500581은 그러한 기술에 대해보다 일반적인 논의를하고 있습니다.
Daniel James Bryars


2
@phoog "결과적으로 응용 프로그램 코드는 동일한 시드가 다른 버전의 .NET Framework에서 동일한 의사 랜덤 시퀀스를 생성한다고 가정해서는 안됩니다." -몰라요, 제겐 꽤 분명해 보입니다. 그러나이 경고에도 불구하고 기존 프로그램을 중단하지 않고 실제로 변경할 수 없다면 놀라지 않을 것입니다.
Roman Starkov 2014

2
@phoog : 당신은 한 가지를 말하고 정반대입니다. 당신은 직접적으로 모순되고 있습니다.
Timwi 2014

53

먼저 연결 한 프레젠테이션은 보안 목적으로 난수에 대해서만 설명합니다. 따라서 Random비보안 목적으로 나쁘다고 주장하지 않습니다 .

그러나 나는 그것이 있다고 주장한다. .net 4 구현에는 Random여러 가지 결함이 있습니다. 난수의 품질에 신경 쓰지 않는 경우에만 사용하는 것이 좋습니다. 더 나은 타사 구현을 사용하는 것이 좋습니다.

결함 1 : 시딩

기본 생성자는 현재 시간으로 시드됩니다. 따라서 Random짧은 시간 프레임 (약 10ms) 내에 기본 생성자 로 생성 된 모든 인스턴스 는 동일한 시퀀스를 반환합니다. 이것은 문서화되고 "설계에 따라"입니다. Random각 스레드 실행의 시작 부분에 단순히 인스턴스를 만들 수 없기 때문에 코드를 다중 스레드하려는 경우 특히 짜증이납니다 .

해결 방법은 기본 생성자를 사용할 때 각별히주의하고 필요한 경우 수동으로 시드하는 것입니다.

여기서 또 다른 문제는 시드 공간이 다소 작다는 것입니다 (31 비트). 따라서 Random완벽하게 임의의 시드로 50k 인스턴스를 생성 하면 아마도 생일 역설 로 인해 하나의 난수 시퀀스를 두 번 얻을 수 있습니다. 따라서 수동 파종도 쉽지 않습니다.

결함 2 :에서 반환 된 난수의 분포 Next(int maxValue)가 편향 됨

Next(int maxValue)분명히 균일하지 않은 매개 변수가 있습니다 . 예를 들어 계산 r.Next(1431655765) % 2하면 0샘플의 약 2/3를 얻을 수 있습니다. (답변 끝에 샘플 코드가 있습니다.)

결함 3 : NextBytes()방법이 비효율적입니다.

의 바이트 당 비용은를 NextBytes()사용하여 전체 정수 샘플을 생성하는 비용만큼 큽니다 Next(). 이것으로부터 나는 그들이 실제로 바이트 당 하나의 샘플을 생성한다고 생각합니다.

각 샘플에서 3 바이트를 사용하는 더 나은 구현 NextBytes()은 거의 3 배 빨라 집니다.

이 결함 덕분 에 내 컴퓨터 (Win7, Core i3 2600MHz) Random.NextBytes()보다 약 25 % 더 빠릅니다 System.Security.Cryptography.RNGCryptoServiceProvider.GetBytes.

누군가가 소스 / 디 컴파일 된 바이트 코드를 검사하면 블랙 박스 분석에서 찾은 것보다 더 많은 결함을 발견 할 것이라고 확신합니다.


코드 샘플

r.Next(0x55555555) % 2 강하게 편향되어 있습니다.

Random r = new Random();
const int mod = 2;
int[] hist = new int[mod];
for(int i = 0; i < 10000000; i++)
{
    int num = r.Next(0x55555555);
    int num2 = num % 2;
    hist[num2]++;
}
for(int i=0;i<mod;i++)
    Console.WriteLine(hist[i]);

공연:

byte[] bytes=new byte[8*1024];
var cr=new System.Security.Cryptography.RNGCryptoServiceProvider();
Random r=new Random();

// Random.NextBytes
for(int i=0;i<100000;i++)
{
    r.NextBytes(bytes);
}

//One sample per byte
for(int i=0;i<100000;i++)
{   
    for(int j=0;j<bytes.Length;j++)
      bytes[j]=(byte)r.Next();
}

//One sample per 3 bytes
for(int i=0;i<100000;i++)
{
    for(int j=0;j+2<bytes.Length;j+=3)
    {
        int num=r.Next();
        bytes[j+2]=(byte)(num>>16);   
        bytes[j+1]=(byte)(num>>8);
        bytes[j]=(byte)num;
    }
    //Yes I know I'm not handling the last few bytes, but that won't have a noticeable impact on performance
}

//Crypto
for(int i=0;i<100000;i++)
{
    cr.GetBytes(bytes);
}

1
흥미롭게도, 당신의 발견을 확인할 수 있습니다 : 내 컴퓨터에서 Next (1431655765)는 또한 어떤 시드로도 2/3를줍니다. 1431655765의 마법은 무엇입니까? 이 번호에 어떻게 도착 했습니까?
citykid

1
@citykid 숫자를 16 진수 또는 비트로보십시오. Random31 비트 정수를 지정된 상한을 가진 숫자로 변환하는 데 사용 하는 모호한 방법에서 마술이 발생 합니다. 세부 사항을 잊었지만 randomValue * max / 2^{31}.
CodesInChaos

1431655765_10 = 1010101010101010101010101010101_2
Tim S.

6
흠. 그렇다면 C # 용 Random 구현을 사용하는 것이 좋습니다.
Arsen Zahray 2014

1
Next()여기서 여러분이 시연 한의 분포의 불균일성 인 Holy cow 는 매우 놀라운 버그이며, 처음 발견 한 결과를 작성한 지 6 년이 지난 지금도 여전히 존재합니다. ( 문서"유한 한 숫자 집합에서 동일한 확률로 의사 난수를 선택 합니다 "라고 주장 하기 때문에 "결함"이 아니라 "버그"라고 말합니다 . 그렇지 않으며 여기에있는 코드가이를 증명합니다.)
Mark Amery

24

System.Random은 암호화 보안 난수를 생성하지 않기 때문에 훨씬 더 성능이 좋습니다.

무작위 데이터로 4 바이트 버퍼를 1,000,000 번 채우는 간단한 테스트는 Random의 경우 49ms, RNGCryptoServiceProvider의 경우 2845ms가 걸립니다. 채우는 버퍼의 크기를 늘리면 RNGCryptoServiceProvider의 오버 헤드가 덜 관련성이 있으므로 차이가 좁아집니다.


2
실제 테스트로 시연 해주셔서 감사합니다.
Lernkurve

3
가혹하다고 생각할 수 있지만 벤치 마크 코드를 포함하지 않고 성능 벤치 마크 결과를 게시하는 경우 -1입니다. 의 성능 특성하더라도 Random하고 RNGCryptoServiceProvider(모든 나는 그들이했습니다 수 있습니다 알고있는) 지난 팔년에서 변경되지 않은, 나는 충분히 그 코드 벤치 마크의 결과를 신뢰하지 스택 오버플로에 사용되는 완전히 깨진 벤치 마크를 보았다 공개적으로 사용할 수 없습니다.
Mark Amery

21

가장 명백한 이유가 이미 언급되었으므로 여기에 더 모호한 이유가 있습니다. 일반적으로 암호화 PRNG는 "실제"엔트로피로 계속해서 다시 시드되어야합니다. 따라서 CPRNG를 너무 자주 사용하면 시스템의 엔트로피 풀이 고갈 될 수 있으며 (CPRNG 구현에 따라) 시스템의 엔트로피 풀이 약해 지거나 (따라서 공격자가 예측할 수 있도록 허용) 충전을 시도하는 동안 차단됩니다. 엔트로피 풀 (따라서 DoS 공격에 대한 공격 벡터가 됨).

어느 쪽이든, 귀하의 애플리케이션은 이제 귀하와 달리 CPRNG의 암호화 속성에 크게 의존 하는 완전히 관련없는 다른 애플리케이션에 대한 공격 벡터가되었습니다 .

이것은 Linux를 실행하는 헤드리스 서버 (마우스 및 키보드 입력과 같은 엔트로피 소스가 없기 때문에 자연스럽게 엔트로피 풀이 다소 작은)에서 관찰 된 실제 실제 문제인 BTW이며, 응용 프로그램 /dev/random에서 모든 종류에 대해 커널 CPRNG를 잘못 사용합니다. 올바른 동작은 작은 시드 값을 읽고이를 /dev/urandom사용하여 자신의 PRNG 를 시드하는 것 입니다.


엔트로피와 엔트로피 고갈에 대한 위키피디아 기사와 다른 인터넷 소스를 읽었는데 이해가 잘 안됩니다. 난수 생성기에 시스템 시간, 여유 바이트 수 등을 제공 할 때 어떻게 엔트로피 풀을 고갈시킬 수 있습니까? 다른 사람들이 난수를 예측하는 공격 벡터로 어떻게 사용할 수 있습니까? 쉬운 예를 제공 할 수 있습니까? 아마도이 토론은 오프라인 상태 여야합니다. en.wikipedia.org/wiki/Entropy_%28computing%29
Lernkurve

3
시스템 시간은 예측 가능하기 때문에 엔트로피 소스가 아닙니다. 사용 가능한 바이트 수에 대해서는 잘 모르겠지만 고품질 엔트로피 소스라고 생각합니다. 서버에 더 많은 요청을 보내면 공격자는 사용 가능한 바이트 수를 줄여 부분적으로 결정적으로 만들 수 있습니다. 응용 프로그램은 엔트로피 풀을 고갈시켜 다른 보안에 중요한 응용 프로그램이 덜 난수를 사용하도록하거나 엔트로피 소스가 보충 될 때까지 기다리기 때문에 공격 벡터가됩니다.
quant_dev

예를 들어 32 비트 시드를 사용하는 의사 난수 생성기가 있으면 무차별 대입 공격이 매우 쉬울 수 있습니다. 64 비트 시드조차도 생일 공격의 대상이 될 수 있습니다. 하지만 씨앗이 그보다 훨씬 커지면 위험을 잘 알지 못합니다. 출력의 각 바이트에 대해 128 비트 상태를 블록 암호화 알고리즘을 통해 전달한 다음 하위 8 비트를 출력하는 랜덤 생성기가있는 경우, 공격자가 몇 기가 바이트 연속 출력 바이트를 사용하더라도 어떻게 상태를 유추 할 수 있습니까? 암호화 알고리즘 자체?
supercat 2013

11

온라인 카드 게임이나 로터를 프로그래밍하는 경우 순서가 추측하기 거의 불가능한지 확인하고 싶을 것입니다. 그러나 사용자에게 오늘의 인용문을 표시하는 경우 보안보다 성능이 더 중요합니다.


9

이것은 어느 정도 길이 논의되었지만 궁극적으로 성능 문제는 RNG를 선택할 때 두 번째 고려 사항입니다. 방대한 RNG 배열이 있으며 대부분의 시스템 RNG가 구성하는 통조림 Lehmer LCG는 최고도 아니고 반드시 가장 빠른 것도 아닙니다. 오래되고 느린 시스템에서는 훌륭한 타협이었습니다. 그 타협은 요즘 거의 관련이 없습니다. A) 물건이 이미 만들어졌고,이 경우에 '바퀴를 재발 명'할 실제 이유가없고, B) 방대한 사람들이 그것을 위해 그것을 사용할 이유가 있기 때문입니다. '충분하다'.

궁극적으로 RNG의 선택은 위험 / 보상 비율로 귀결됩니다. 예를 들어 비디오 게임과 같은 일부 응용 프로그램에서는 위험이 전혀 없습니다. Lehmer RNG는 적절하고 작고 간결하며 빠르며 잘 이해되고 '기본 제공'입니다.

예를 들어 응용 프로그램이 실제 상금이 포함 된 온라인 포커 게임 또는 복권이고 방정식의 어느 시점에서 실제 돈이 사용되는 경우 'in the box'Lehmer는 더 이상 적합하지 않습니다. 32 비트 버전에서는 기껏 해야 순환 시작하기 전에 2 ^ 32 개의 유효한 상태 만 가능합니다 . 요즘은 무차별 대입 공격의 문이 열려 있습니다. 이와 같은 경우 개발자는 일부 종 의 매우 긴 기간 RNG 와 같은 것으로 이동 하고 아마도 암호 학적으로 강력한 공급자로부터 시드 를 원할 것입니다. 이것은 속도와 보안 사이에 좋은 절충안을 제공합니다. 이 경우, 그 사람은 Mersenne Twister 또는 Multiple Recursive Generator 와 같은 것을 찾고있을 것입니다. 어떤 종류 입니다.

응용 프로그램이 네트워크를 통해 대량의 재무 정보를 전달하는 것과 같은 것이라면 이제 엄청난 위험이 있으며 가능한 모든 보상을 크게 압도합니다. 장갑차는 여전히 존재합니다. 때때로 중무장 한 남자 만이 적절한 보안이기 때문입니다. 저를 믿으세요. 전차, 전투기, 헬리콥터가있는 특수 작전 부대가 재정적으로 타당하다면 선택 방법이 될 것입니다. 이와 같은 경우에는 암호화 된 강력한 RNG를 사용하는 것이 합리적입니다. 얻을 수있는 보안 수준이 원하는만큼 많지 않기 때문입니다. 그래서 당신은 당신이 찾을 수있는만큼 많이 가져갈 것이고, 비용은 시간이나 돈에있어서 매우 멀리 떨어진 2 위 문제입니다. 그리고 그것이 모든 임의의 시퀀스가 ​​매우 강력한 컴퓨터에서 생성되는 데 3 초가 걸린다는 것을 의미한다면, 3 초를 기다릴 것입니다.


3
나는 당신이 당신의 규모에 대해 틀렸다고 생각합니다. 재무 데이터 전송은 매우 빨라야합니다. 거래 알고리즘이 경쟁사보다 0.1ms 더 빨리 결과에 도달 할 수 있다면 매수 / 매도 / 손절 중지 / 호가 명령 대기열에서 더 나은 결과를 얻을 수 있습니다. 3 초는 영원합니다. 이것이 상인들이 엄청나게 좋은 컴퓨터에 투자하는 이유입니다. 이전 답변을 참조하십시오. Crypt.RNG는 새 번호 당 0,0028ms 만 걸립니다. 0.0000028 초이므로 처리하는 데 걸리는 시간과 속도가 얼마나 중요한지 측면에서 9 배 차이가납니다.
Henrik


4

모든 사람이 암호화 보안 난수를 필요로하는 것은 아니며 더 빠른 일반 프린팅으로 더 많은 혜택을 볼 수 있습니다. 아마도 더 중요한 것은 System.Random 번호의 시퀀스를 제어 할 수 있다는 것입니다.

재현 할 수있는 난수를 사용하는 시뮬레이션에서 동일한 시드로 시뮬레이션을 다시 실행합니다. 주어진 잘못된 시나리오를 다시 생성하고 싶을 때 버그를 추적하는 데 유용 할 수 있습니다. 프로그램을 충돌시킨 것과 똑같은 난수 시퀀스로 프로그램을 실행합니다.


2

보안이 필요하지 않은 경우, 즉 암호 적으로 강력한 값이 아닌 상대적으로 불확실한 값을 원할 경우 Random은 사용하기 훨씬 쉬운 인터페이스를 제공합니다.


2

서로 다른 요구는 서로 다른 RNG를 요구합니다. 암호화의 경우 난수를 가능한 한 무작위로 설정해야합니다. Monte Carlo 시뮬레이션의 경우 공간을 고르게 채우고 알려진 상태에서 RNG를 시작할 수 있기를 원합니다.


1
System.Random 만했다면 .. 아, 그래.
user2864740

2

Random 는 난수 생성기가 아니며 결정 론적 의사 난수 시퀀스 생성기이며 역사적 이유로 그 이름을 사용합니다.

사용하는 이유 System.Random는 이러한 속성, 즉 동일한 시드로 초기화 될 때 동일한 결과 시퀀스를 생성하도록 보장되는 결정적 시퀀스를 원하는 경우입니다.

인터페이스를 희생하지 않고 "무작위성"을 향상 시키려면 System.Random여러 메서드 를 재정 의하여 상속 할 수 있습니다 .

결정적 시퀀스를 원하는 이유

진정한 임의성이 아닌 결정 론적 시퀀스를 갖는 한 가지 이유는 반복 가능하기 때문입니다.

예를 들어, 수치 시뮬레이션을 실행하는 경우 (참) 난수로 시퀀스를 초기화하고 사용 된 숫자를 기록 할 수 있습니다.

그런 다음 디버깅 목적으로 똑같은 시뮬레이션 을 반복하려는 경우 대신 기록 된 값으로 시퀀스를 초기화하면됩니다 .

왜이 특별한 시퀀스를 원하십니까?

내가 생각할 수있는 유일한 이유는이 클래스를 사용하는 기존 코드와의 하위 호환성 때문입니다.

간단히 말해서, 나머지 코드를 변경하지 않고 시퀀스를 개선하려면 계속 진행하십시오.


1

나는 지도에 "무작위"일련의 보석 (이미지)을 배치 하는 게임 (iPhone의 Crystal Sliders : 여기 )을 작성하고 원하는대로지도를 회전하고 선택하면 사라졌습니다. -Bejeweled와 비슷합니다. 나는 Random ()을 사용하고 있었고, 전화가 부팅 된 이후로 100ns 틱 수로 시드되었습니다.

나는 그것이 서로 거의 동일한 게임을 생성 할 수 있다는 것이 놀랍다 는 것을 알았습니다 . 90 개 정도의 보석, 2 가지 색상 중 1 ~ 3 개의 보석을 제외하고는 똑같은 두 가지를 얻을 수 있습니다! 90 개의 동전을 던지고 1-3 번 던지는 것을 제외하고 동일한 패턴을 얻는다면, 그것은 거의 불가능합니다! 나는 그것들을 똑같이 보여주는 여러 개의 스크린 샷을 가지고 있습니다. System.Random ()이 얼마나 나쁜지 충격을 받았습니다! 나는 내 코드에서 끔찍하게 잘못 작성하고 잘못 사용하고 있다고 생각했습니다. 나는 틀렸다. 그것은 발전기였다.

실험과 최종 해결책으로 1985 년부터 사용해 왔던 난수 생성기로 돌아갔습니다. 훨씬 더 낫습니다. 더 빠르고 반복되기 전에 1.3 * 10 ^ 154 (2 ^ 521)의주기를가집니다. 원래 알고리즘은 16 비트 숫자로 시드되었지만 32 비트 숫자로 변경하고 초기 시드를 개선했습니다.

원래는 여기에 있습니다.

ftp://ftp.grnet.gr/pub/lang/algorithms/c/jpl-c/random.c

수년에 걸쳐, 나는 이것에 대해 생각할 수있는 모든 난수 테스트를 던졌고, 모든 테스트를 통과했습니다. 나는 그것이 암호화 가치가 있다고는 생각하지 않지만 "return * p ++;"만큼 빠른 숫자를 반환합니다. 521 비트가 다 떨어질 때까지 비트에 대해 빠른 프로세스를 실행하여 새로운 임의의 비트를 만듭니다.

저는 C # 래퍼를 만들었습니다. JPLRandom ()이라고 부르며 Random ()과 동일한 인터페이스를 구현하고 코드에서 호출 한 모든 위치를 변경했습니다.

그 차이는 훨씬 더 좋았습니다. OMG 저는 놀랐습니다. 90 개 정도의 보석 화면을 패턴으로 보는 것만으로도 알 수있는 방법이 없어야했지만, 이에 따라 게임을 긴급 출시했습니다.

그리고 다시는 System.Random ()을 사용하지 않을 것입니다. 나는 그들의 버전이 이제 30 년이 된 것에 의해 날아가는 것에 충격을 받았습니다!

-Traderhut 게임


3
내 첫 번째 추측은 당신이 Random너무 자주 재창조했다는 것 입니다. Next해당 인스턴스를 여러 번 호출 한 경우에만 만들어야 합니다. Random나쁘지만 그렇게 나쁘지 않습니다. 이 문제를 나타내는 한 쌍의 씨앗과 함께 샘플 프로그램을 게시 할 수 있습니까?
CodesInChaos

이 코드는 각 레벨의 시작 부분에 Random ()을 생성합니다 (그러나 레벨 1은 이후 레벨보다 더 큰 문제였습니다) 코드는 대략 다음과 같습니다.
Traderhut Games

Rnd = 새로운 Random ((uint) GameSeed); NextGameSeed = Rnd.Next (2000000000); 각 레벨은 새로운 시드로 생성 된 새로운 랜덤을 사용했습니다.-시드는 각 레벨에 대해 저장되었으므로 맵을 다시 생성하고 일치하는 랜덤 시드의 순서도 확인할 수있었습니다. 이를 통해 게임이 해결 된 유효한 맵 시리즈인지 확인하고 게임을 다시 만들 수 있습니다.
Traderhut Games 2014

그리고 처음에 Random은 System.DateTime.Now.Ticks (또는 0)를 기반으로 생성되었으며 GameSeed는 위의 Rnd.Next ()와 동일한 호출을 사용하여 선택되었습니다. 이것을 할 수 없다면 난수 생성기의 시드에 심각한 문제가있는 것입니다.
Traderhut Games 2014

이것은 원래 질문에 대한 답이 아닙니다!
Mike Dinescu 2015 년

-1

System.Random이 "부정확성"과 편견 때문에 여기에서 부끄러워 졌기 때문에 저는 스스로 확인했습니다.

분포

이 f # 코드는 내 평균적인 컴퓨터에서 정말 멋지게 작동 함을 보여줍니다.

let r = System.Random()
Seq.init 1000000 (fun _ -> r.Next(0,10))
|> Seq.toList
|> Seq.groupBy id
|> Seq.map (fun (v,ls) -> v, ls |> Seq.length)
|> Seq.sortBy fst
|> Seq.iter (printfn "%A")

(0, 100208)
(1, 99744)
(2, 99929)
(3, 99827)
(4, 100273)
(5, 100280)
(6, 100041)
(7, 100001)
(8, 100175)
(9, 99522)    

프레임 워크 버전, 시스템, 운영 체제는 모두 차이를 만들 수 있습니다. 컴퓨터에서 대화 형 F #으로 코드를 입력하고 직접 시도해보세요. Cyrptography를 위해 나는 읽었다

let arr = [| 0uy |]
let rr = System. Security.Cryptography.RandomNumberGenerator.Create()
Seq.init 1000000 (fun _ -> rr.GetBytes(arr); arr.[0])
|> Seq.toList
|> Seq.groupBy id
|> Seq.map (fun (v,ls) -> v, ls |> Seq.length)
|> Seq.sortBy fst
|> Seq.take 10 // show first 10 bytes
|> Seq.iter (printfn "%A")

// distribution of first 10 bytes
(0uy, 3862)
(1uy, 3888)
(2uy, 3921)
(3uy, 3926)
(4uy, 3948)
(5uy, 3889)
(6uy, 3922)
(7uy, 3797)
(8uy, 3861)
(9uy, 3874)

공연

#time

let arr = [| 0uy |]

let r = System.Random()
Seq.init 1000000 (fun _ -> r.NextBytes(arr); arr.[0] |> int64) |> Seq.sum

Real: 00:00:00.204, CPU: 00:00:00.203, GC gen0: 45, gen1: 1, gen2: 1
val it : int64 = 127503467L

let rr = System. Security.Cryptography.RandomNumberGenerator.Create()
Seq.init 1000000 (fun _ -> rr.GetBytes(arr); arr.[0] |> int64) |> Seq.sum

Real: 00:00:00.365, CPU: 00:00:00.359, GC gen0: 44, gen1: 0, gen2: 0
val it : int64 = 127460809L

이는 1 : 2 관계와 암호화 버전의 다소 좋은 메모리 동작을 제안합니다.

결론

주로 훨씬 더 좋은 API, 성능 및 배포가 상당히 우수한 System.Random이 선호됩니다. System.Random은 또한 라이브러리 종속성을 줄일 수 있으며 프레임 워크가 포팅 된 경우 System.Random은 Crypto 변형보다 먼저 사용할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.