2013-10-07 2 views
0

기본 RandomNumberGenerator 구현을 사용하여 지정된 범위 내에서 Int32 값을 생성하는 함수를 작성하려고합니다.임의의 바이트를 지정된 범위의 정수로 변환

void GenerateRandom (int [] data, int minInclusive, int maxExclusive) 
{ 
    int size = 0; 
    int length = 0; 
    byte [] bytes = null; 

    size = (int) Math.Ceiling(Math.Log(Math.Abs(maxExclusive - minInclusive), 2)); 
    length = data.Length * size; 
    var bytes = new byte [length]; 

    using (RandomNumberGenerator generator = RandomNumberGenerator.Create()) 
    { 
     generator.GetBytes(bytes); 
    } 

    // How to effectively convert this `byte []` to an `int []` within the specified range? 
} 

한 시도 (data.Length * ((int) Math.Ceiling(Math.Log(Math.Abs(maxExclusive - minInclusive), 2)))) 길이의 랜덤 바이트 배열을 생성 int로 각 바이트 X 번호를 조합 하였다. 지정된 범위에 관계없이,이 접근법은 물론 다수의 최상위 바이트가 0 일 가능성이 거의 없으므로 큰 값으로 향하는 큰 편향의 단점이 있습니다.

모든 의견을 보내 주시면 감사하겠습니다. 여기에 .NET을 사용하고 있지만 플랫폼/언어는 중요하지 않습니다. 개념적 힌트를 찾고 있습니다.

.NET의 Random 클래스에 이미 익숙하지만 RandomNumberGenerator를 사용할 수있는 동안이 작업을 수동으로 수행하는 방법을 알고 싶다는 점에 유의하십시오.

+0

@MatthewWatson : 이것은 'System.Security.Cryptography' 네임 스페이스에있는 추상 클래스입니다. 그것을 밖으로 시도하고 싶지 않으면, 당신은이 질문의 목적을 위해 그것을 무시할 수 있습니다. –

+0

죄송합니다. 게시 한 직후에 그 사실을 발견했습니다. –

답변

1
unsafe static int[] GenerateRandom(int length, int minInclusive, int maxExclusive) 
{ 
    var bytes = new byte[length * 4]; 
    var ints = new int[length]; 

    var ratio = uint.MaxValue/(double)(maxExclusive - minInclusive); 

    using (RandomNumberGenerator generator = RandomNumberGenerator.Create()) 
    { 
     generator.GetBytes(bytes); 
     fixed(byte* b = bytes) 
     { 
      uint* i = (uint*)b; 
      for(int j = 0; j < length; j++, i++) 
      { 
       ints[j] = minInclusive + (int)(*i/ratio); 
      } 
     } 
    } 

    return ints; 
} 

나는 약간의 테스트를 실행했습니다

var ints = GenerateRandom(1000000, 0, 300); 

var groups = ints.GroupBy(x => x).Select(g => new { value = g.Key, count = g.Count() }); 
var hist = Enumerable.Range(0, 300).Join(groups, x => x, g => g.value, (x, g) => new { value = x, count = g.count }).ToList(); 

var max = hist.OrderByDescending(x => x.value).First(); 
var min = hist.First(); 

그리고 결과는 min.count = 3301max.count = 3358과 매우 모든 숫자에 걸쳐 임의0300 사이입니다.

관련 문제