2012-02-22 4 views
2

나는 부드럽고 물결 모양의 색상을 만들기 위해 무작위로 결정된 색상으로 여러 개의 패널을 만들고 20 밀리 초마다 임의의 상수로 증가/감소시킬 프로그램을 만들고 있습니다. 이를 위해 방금 Random 클래스의 Next (int) 메서드를 사용했습니다. 단일 인스턴스의 경우 완벽하게 작동합니다. 프로그램을 실행할 때마다 다른 색이 다른 속도로 변경됩니다. 문제는 여러 패널을 만들려고 할 때 발생합니다. 모두는 아니지만 대부분이 서로 똑같이 보이고 행동하며 나와 임의로 생성 된 숫자가 모두 동일 함을 의미합니다. 나는 이것이 빠른 연속으로 모든 의사 난수를 생성 한 결과로 모든 것이 같은 씨앗을 기반으로한다고 가정합니다.C#에서 신속하게 난수 생성하기

랜덤 정수를 연속적으로 생성하여 Random 클래스를 사용하여 동일한 것이 아닌지 확인하는 것보다 나은 방법이 있습니까? 이미 C#에 내장 된 방법이 없으면 의사 랜덤 넘버 생성기를 개발하는 간단한 방법이 있습니까? (이것이 C#을 처음 사용하는 첫 번째 방법입니다)?

+0

매번 PRNG 개체를 다시 초기화하거나 다시 만드시겠습니까? 알맞은 PRNG는 사용자가 설명하는 것과 동일한 숫자를 안정적으로 생성해서는 안됩니다. –

답변

5

기본 생성자를 사용하여 무작위 클래스의 여러 인스턴스를 사용하지 마십시오. 모두 동일한 타임 슬라이스 내에서 초기화되는 경우 모두 동일한 시드를 가지며 동일한 난수 시퀀스를 생성합니다. you can pass in a seed이라는 생성자를 사용하고 각 인스턴스에 다른 시드를 전달합니다.

Random rand0, rand1, rand2; 

void init() 
{ 
     int baseSeed = (int) DateTime.Now.Ticks; 
     rand0 = new Random(baseSeed); 
     rand1 = new Random(baseSeed + 1); 
     rand2 = new Random(baseSeed + 2); 
} 

또한 당신은 단지 그들이 동일한 스레드에 있습니다 경우 모든 패널에 대해 같은 임의의 객체를 사용, 스레드 당 하나의 객체가 필요합니다. 당신은 암호화 보안 난수가 필요하지 않은 경우

+1

또는, 임의로 중앙 인스턴스 하나를 생성하고 모든 난수 생성에 사용하십시오. –

+0

@ AvnerShahar-Kashtan : 음, 스레드 당 하나. 스레드로부터 안전하지 않습니다. –

+0

기존의 난수 생성기를 재사용하는 것은 매번 새로운 인스턴스를 시드로 생성하는 것보다 일반적으로 더 간단합니다. 결국 씨앗을 주변에 보관해야하는 경우 Random 대신 참조를 유지하는 것이 좋습니다. –

2

Random 괜찮 -하지만 기회는 당신이 새로운 인스턴스 당신이 번호가 필요 할 때마다 생성보다는 전반에 걸쳐 하나 인스턴스를 사용하고 있습니다.

Random의 새 인스턴스를 만들면 "현재 시간"이 시드가됩니다. 따라서 연속해서 두 개를 만들면 동일한 시드와 동일한 숫자를 가진 두 개의 인스턴스가 생성됩니다 (같은 전화를 사용할 때).

일반적으로 Random의 단일 인스턴스를 사용하는 것이 좋습니다. 스레드가 안전하지 않으므로 스레드 당 하나씩 사용하는 것이 좋습니다.

다양한 접근을 위해 내 article on the topic을 참조하십시오.

1

나는 RNGCryptoServiceProvider을 선호합니다. 대략 Random과 같으며 비공식 테스트에서 더 많은 고유 한 값을 생성하는 경향이 있습니다. 또한 시드 (seeding)와 관련된 바람직하지 않은 행동 (예 : 다른 사람들이 묘사하는 행동)을 피하십시오.

그러나 고유성을 보장 할 수 없습니다 (그렇지 않으면 무작위가 아닙니다). 고유 한 값 (원하지 않는 소리)을 영구히 추적해야하는 경우 또는 메모리에 고유 한 숫자 세트를 생성하는 데 신경 쓰면 임의 값이 키인 Dictionary을 데이터베이스에 사용할 수 있습니다. 키가 이미 있으면 값을 거부하고 다른 값을 생성합니다. 당신은 임의의 숫자의 동일한 시리즈를 생산하는 Random 클래스의 여러 인스턴스가있는 경우

using System.Security.Cryptography; 

... 

RNGCryptoServiceProvider crypto = new RNGCryptoServiceProvider(); 
byte[] bytes = new byte[8]; 
crypto.GetBytes(bytes); 
long value = BitConverter.ToInt64(bytes, 0); 
1

는, 당신은 같은 종자를 사용하여 각 인스턴스를 생성해야합니다.예를 들어 :

그에 대한 가장 그럴듯한 설명은이 같은 그들 모두를 만드는 것입니다 :

var rng = new Random(); 

시간에 같은 지점에서 각 인스턴스를 생성. 이 생성자는 현재 시간을 사용하여 RNG를 시드하고 동일한 시점에 모두 생성하면 모두 동일한 시간에 시드됩니다.

다른 시드로 각 인스턴스를 만들어 문제를 해결하십시오. 또는 단일 RNG를 만들어 모든 패널간에 공유 할 수 있습니다.

0

위에서 언급 한 것처럼 임의의 클래스의 단일 인스턴스를 사용할 수 있습니다. 그러나 어떤 이유로 이것이 바람직하지 않은 경우 (즉, 여러 스레드를 실행하고 경합하지 않으려는 경우), 각 생성기의 시드를 무작위 또는 의사로 초기화하면 여러 인스턴스를 사용할 수 있습니다. 임의로 생성 된 시드

이 초기 시드 생성의 경우 동일한 임의 생성기를 사용해야합니다.