2014-11-23 35 views
2

這是我用來生成隨機字節數組的代碼。這是完全沒問題,唯一的是 有一個(或多個)我不想要的數字。我的問題是,如何確保這些不需要的數字不包含在結果中,而不必經過每個結果?生成隨機字節數組而不會忽略值

Random rnd = new Random(); 
    Byte[] bytes = new Byte[50]; 
    rnd.NextBytes(bytes); 

對於一個字節,我使用這個函數;

int b = rnd.Next(min, (max + 1)) 
    return (byte) b; 

其中我可以控制結果範圍,但重複調用此函數不會給出好的結果。

+0

你不想要什麼號碼?你能展示一個包含這樣的數字的樣例輸出,以及你期望它的樣子嗎? – 2014-11-23 15:48:02

+0

「,但重複調用此函數不會給出好的結果。」這是什麼意思?你每次打電話時都收到相同的號碼嗎? – 2014-11-23 15:48:15

回答

4

您的問題可以用蒙特卡洛算法輕鬆解決。這就是@SteveLillis正在做的事情,但這是一個不完整的答案。所以這裏是完整的。

void Main() 
{ 
    var exclusions = new HashSet<byte> { 1, 200, 58, 11, 66, 9 }; 

    var results = RandomBytes() 
        .Where(b => exclusions.Contains(b) == false) 
        .Take(50) 
        .ToArray(); 
} 

public IEnumerable<byte> RandomBytes() 
{ 
    var random = new Random(); 
    byte[] buffer = new byte[32]; 
    while(true) 
    { 
     random.NextBytes(buffer); 
     foreach(var ret in buffer) 
     { 
      yield return ret; 
     } 
    } 
} 

RandomBytes()是一個隨機字節流,很簡單吧?

然後我們排除任何我們不喜歡的流,Where(b => exclusions.Contains(b) == false)。哈希集是爲了「效率」,但它不會幫助byte(只是因爲習慣)。

Take(50),我們只從流中獲得50個。

ToArray以數組形式給出結果。

+0

產量和拉姆達... COOL @Aron !!!但我不明白爲什麼32緩衝區陣列?一個數組是好的,因爲它是一個隨機數,你不這麼認爲嗎? – 2014-11-23 19:59:05

+0

@sambyte我不完全確定'.NextBytes'的實現是什麼。一般來說,當他們以這種方式公開功能時,通常使用「較大」緩衝區運行起來更便宜。但是,是的...在功能上,'byte [1]'將完全相同。 – Aron 2014-11-24 03:06:08

0

如果數字不太可能繼續提升,您可以繼續嘗試,直到生成「好」數字。

var badNumbers = new int[] { 244, 100 }; 
int b = 0; 
do 
{ 
    b = rnd.Next(min, (max + 1)); 
} while (badNumbers.Contains(b)); 

此外,請確保你宣佈你的隨機對象,並反覆使用它,不要讓實例化一個新的,因爲默認情況下的種子是從時間採取,如果你實例2個隨機量過快一個之後,他們會生成相同的號碼。

0

您可以在單獨的數組中生成允許值(相對於最小值,最大值和忽略的值),並將其用於目標數組生成。我們來考慮下面的例子。

幫助功能:

byte[] GenerateAllowableValues(byte min, byte max, byte[] ignore) 
{ 
    var list = new List<byte>(); 
    for (byte i = min; i <= max; i++) 
    if (!ignore.Contains(i)) 
     list.Add(i); 
    return list.ToArray(); 
} 

byte[] GenerateRandomArray(Random random, byte[] allowableValues, int length) 
{ 
    var array = new byte[length]; 
    for (int i = 0; i < length; i++) 
    array[i] = allowableValues[random.Next(allowableValues.Length)]; 
    return array; 
} 

用法:

void Main() 
{ 
    var random = new Random(42); 
    var allowableValues = GenerateAllowableValues(10, 20, new byte[] { 12, 15 }); 
    var randomArray = GenerateRandomArray(random, allowableValues, 5); 
    foreach (byte b in randomArray) 
    Console.WriteLine(b); // 18 11 11 16 11 
} 
0

構建你想排除那些你不這樣做,然後選擇一個隨機元素從陣列50倍的字節數組;

var rnd = new Random(); 
var exclusions = new byte[] { 1, 200, 58, 11, 66, 9 }; 
var candidates = Enumerable.Range(0, 255).Where(i => !exclusions.Contains((byte)i)).ToArray(); 

var results = new byte[50]; 
for (var i = 0; i < results.Length; i++) 
{ 
    results[i] = (byte)candidates[rnd.Next(0, candidates.Length - 1)]; 
}