2013-07-02 3 views
3

관심 없기 때문에 C#과 함께 제공되는 임의의 클래스로 놀고 있습니다. 나는 미래를 예측하려고 노력하고있다. 의사 랜덤이므로 숫자를 예측할 수있는 방법이 있어야합니다. 내가 생각할 수있는 유일한 방법은 무차별 한 힘 (모든 가능한 씨앗을 얻고 그 안에있는 난수 패턴을 찾는 것)이지만 씨앗이 -2,147,483,647에서 2,147,483,647 사이의 값을 가질 수 있기 때문에 너무 많은 처리 능력이 될 것이라고 나는 믿는다. 이 두 클래스가 같은 순서로 같은 난수를 제공 할 것입니다C# 무작위 인스턴스의 시드 결정

new Random() == new Random(Environment.TickCount) 

그 :

은 지금까지 나는 것으로 확인되었습니다.

임의의 클래스 인스턴스의 시드를 확인하는 것이 가능합니까? Random 클래스가 인스턴스화 될 때 Environment.TickCount를 알 수 있다면 난수를 예측할 수 있지만 수행 할 수 있는지 여부는 알 수 없습니다.

+1

당신은 찾을 수 있습니다 [이 문서] (http://ericlippert.com/2013/05/02/producing-permutations-part-six/)와 [속편] (흥미로운 Eric Lippert의 http://ericlippert.com/2013/05/06/producing-permutations-part-seven/). 그는 당신이하고있는 방식으로 미래를 예측할 것을 사용자들에게 요구했다. 씨앗을 강요하는 것은 특히'Environment.TickCount' 값이 더 많을 때 더 빨리 생각할 수 있습니다. – Brian

+0

고마워요 브라이언! 매우 흥미로운!! 나는 어제를 앞두고 무력을 시도했다. 당신 말이 맞아요, 아주 빠릅니다. 나는 15 개의 숫자 시퀀스를 맞추었고, 10 000 000 개의 시드를 검색 할 때 평균 22.3 초의 시드 숫자를 발견했습니다. 이 결과는 꽤 표준적인 듀얼 코어 노트북에서 나온 것입니다. 이 기사는 매우 흥미 롭습니다. 일부 종자 값이 다른 종자 값보다 가능성이 높습니다. – Corne

답변

5

는, 숫자를 예측할 수있는 방법이 있어야합니다.

실제로; 당신이 (특히 inext, inextpSeedArray에 - 총 그래서 58 개 int 값) 내부 상태를 알고있는 경우, 당신은 Next(), Next() 요구 (예를 들어, 정확한 순서로 요청하고자하는 정확한 작업을 알고 , NextBytes()Next(), NextBytes(), Next()과 매우 다릅니다. 그러면 정확한 정확한 추측을 할 수 있습니다. 그게 전부 포인트 시드 PRNG의 - 반복 가능한 임의성을 허용합니다, 당신이 이벤트를 재생할 수 있어야 할 때 많은 시나리오에서 유용합니다.

그래서 : 나는 당신이 이제까지 원래 을 다시 얻을 수 있다고 생각하지 않지만, 미래 (보다는 과거) 당신이 씨앗을하지 않아도을 예측하기 - 당신은 58 int 값이 필요합니다.

그러나! 무작위성이 인 항목이 인 경우 임의의 공급자 무작위 제공자를 사용해야하며 이 아니고은 반복 가능하거나 추측 할 수 있어야합니다.

예를 들어

:

static class Program { 
    static Random Clone(this Random source) 
    { 
     var clone = new Random(); 
     var type = typeof(Random); 
     var field = type.GetField("inext", 
      BindingFlags.Instance | BindingFlags.NonPublic); 
     field.SetValue(clone, field.GetValue(source)); 
     field = type.GetField("inextp", 
      BindingFlags.Instance | BindingFlags.NonPublic); 
     field.SetValue(clone, field.GetValue(source)); 
     field = type.GetField("SeedArray", 
      BindingFlags.Instance | BindingFlags.NonPublic); 
     int[] arr = (int[])field.GetValue(source); 
     field.SetValue(clone, arr.Clone()); 
     return clone; 
    } 
    static void Main() 
    { 
     Random rand = new Random(); 
     var clone = rand.Clone(); 
     Console.WriteLine("My predictions:"); 
     Console.WriteLine(clone.Next()); 
     Console.WriteLine(clone.Next()); 
     Console.WriteLine(clone.Next()); 
     Console.WriteLine("Actual:"); 
     Console.WriteLine(rand.Next()); 
     Console.WriteLine(rand.Next()); 
     Console.WriteLine(rand.Next()); 
    } 
} 
+1

정말 멋지다! :) 사소한 단조 로움 :'NextDouble' 또는'Next'는별로 다르지 않습니다. 'NextDouble()'은'Next()/(double) Int32.MaxValue'와 동일합니다. 그러나 더 중요하게, 그것은 다음 숫자, 즉 Next, NextDouble, Next와 Next, Next, Next에 영향을 미치지 않을 것입니다. 1과 3에 같은 숫자가 생깁니다. –

+0

@DanielHilgarth fair enough; 나는 NextDouble()이 어떻게 구현되는지를 보지 않았다. 아마도'NextBytes()'가 더 좋은 예입니다. 내가 시도한 것은 샘플을 채취하는 것이 중요하다는 것입니다. 나는 바보 같이'NextDouble'을 가정했으며, 64 비트는 2 샘플을 사용했습니다. 사실 사실이 아닙니다. 그러나'NextBytes'는'buffer.Length' 샘플을 사용하기 때문에'NextBytes' 대신'NextDouble'을 사용하십시오. 여기서'buffer.Length'는'1'이 아니며, 제가 말하려고했던 것입니다. –

+0

와우! 꽤 굉장합니다! 그리고 예, 중요한 암호화 난수 처리기가 중요한 난수의 경우에 사용되어야하지만 많은 프로그래머는 문제를 해결하지 않을 것입니다. – Corne

3

Random의 구현은 시드를 어디에도 저장하지 않습니다. 대신 시드 배열을 사용합니다. 불행히도 씨앗을 결정할 방법이 없습니다.

씨앗을 취 임의의 생성자는 다음과 같다 : 당신은 그것을 어디 씨앗을 저장하지 않는 것을 볼 수 있습니다

public Random(int Seed) 
{ 
    this.SeedArray = new int[0x38]; 
    int num4 = (Seed == 0x80000000) ? 0x7fffffff : Math.Abs(Seed); 
    int num2 = 0x9a4ec86 - num4; 
    this.SeedArray[0x37] = num2; 
    int num3 = 0x1; 
    for (int i = 0x1; i < 0x37; i++) 
    { 
     int index = (0x15 * i) % 0x37; 
     this.SeedArray[index] = num3; 
     num3 = num2 - num3; 
     if (num3 < 0x0) 
     { 
      num3 += 0x7fffffff; 
     } 
     num2 = this.SeedArray[index]; 
    } 
    for (int j = 0x1; j < 0x5; j++) 
    { 
     for (int k = 0x1; k < 0x38; k++) 
     { 
      this.SeedArray[k] -= this.SeedArray[0x1 + ((k + 0x1e) % 0x37)]; 
      if (this.SeedArray[k] < 0x0) 
      { 
       this.SeedArray[k] += 0x7fffffff; 
      } 
     } 
    } 
    this.inext = 0x0; 
    this.inextp = 0x15; 
    Seed = 0x1; 
} 

.

(이에 대한 이상한 점은 어떤 이상한 이유로 끝에 종자 변수를 오른쪽으로 1 할당 한 -하지만 그건 정말 관련이 아니에요, 그것은 그냥 좀 이상한.) 당신은 당신의 자신을 쓸 수

나중에 검색 할 시드 값을 유지하는 Random의 랩퍼 클래스. 구현은 Seed을 기억하고 : 그것은 의사 랜덤으로

public class MyRandom: Random 
{ 
    public MyRandom() : this(Environment.TickCount) 
    { 
    } 

    public MyRandom(int seed) : base(seed) 
    { 
     this.seed = seed; 
    } 

    public int Seed 
    { 
     get { return seed; } 
    } 

    private readonly int seed; 
} 
+1

나는 시드가 1로 설정되어 값이 메모리에 저장되는 시간을 줄임으로써 누군가가 추출 할 수있는 기회를 줄인다 고 가정합니다. – Tobsey

+3

@Tobsey 만약'seed '가 가능하다면'Random' IMO를 사용하는 것이 완전히 부적절 할 것입니다 - 이것은 암호화 된 랜덤 공급자를 사용해야하는 시나리오가 될 것입니다 –

+0

매우 흥미로운 매튜! – Corne