2011-11-19 29 views
3

我想生成八位(uint8_t)隨機數,這樣我就排除了已經指定的一組衆所周知的數字。基本上從0x00到0xFF的數字,但我有一定範圍內的數字,我不想出現。如何生成8位(僞)隨機數,以便排除某些已知數字?

我想只是用允許的數字填充矢量,然後選擇一個(僞)隨機索引並使用它。

我懷疑他們可能是嚴重缺乏這個,所以尋找線索/建議。該解決方案不一定是火箭科學檔次,但只是很簡單的「出現」隨機:)

編輯:我不想使用外部庫,例如升壓,因爲我對ARM的嵌入式解決方案

編輯工作:我不支持C++ 11

+5

您的解決方案聽起來不錯。去吧。 (不知道這應該是一個答案或評論,但實際上沒有什麼需要添加的;從數組中隨機選擇元素總是會發生......) – sarnold

+0

+1這是一種常用的方法來選取帶有禁止值的隨機數。 – Dalmas

+0

如果您的禁止編號列表在運行時不會改變,並且如果256字節對您而言不是很多內存,那麼我會說您的是最好的解決方案。 – TonyK

回答

1
#include <iostream> 
#include <algorithm> 
#include <ctime> 

int main() 
{ 
    srand(time(0)); 
    int exclude [] = {4,6,2,1}; 
    // Test Values for Exclude 
    std::sort(exclude, exclude + 4); 

    int test = 0; 
    for (int i = 0; i < 50; ++i) 
    { 
     // While we haven't gotten a valid val. 
     while (std::binary_search(exclude, exclude + 4, test = (rand() % 256))); 
     std::cout << test << std::endl; // Print matched value 
    } 
    return 0; 
} 

我認爲這會比@ IceCoder的解決方案快一點。

+0

是的,更大的'排除'陣列也更快。由於他打算在少量的數字上工作,我還添加了一個新的算法,每個數字只執行一次檢查。 – AlQafir

+0

哦!事件更好。 TA。將嘗試這個和我自己的建議 – dubnde

2
unsigned char unwanted[] = {1, 2, 3}; 
int unwanted_len = 3; 
bool found; 

do 
{ 
    unsigned char val = static_cast<unsigned char>(rand() % 0xff); 
    found = true; 

    for(int i = 0; i < unwanted_len; i++) 
    if(unwanted[i] == val) 
    found = false; 
} while(!found); 

把它放在一個函數中,你就完成了。您必須包含cstdlib才能使其工作。

編輯:

其他可能性(因爲你工作的範圍限制):

bool nums[256]; 

void init_r() 
{ 
for(int i = 0; i < 256; i++) 
    nums[i] = true; 
} 

void get_rnd() 
{ 
int n; 
do 
{ 
    n = rand() % 256; 
} while(nums[n] == false); 
return n; 
} 

您可以通過作用於nums陣列上禁用任何你想要的號碼。

+0

什麼是預期的運行時間? :-) –

+0

這將不會有一個非常愉快的統計分佈。 – bmargulies

+0

我是一個緩慢的算法,但是當他問簡單的代碼時,會更簡單些?此外,由於可接受結果的範圍僅爲256,因此大量不需要的數組將使其無法使用。我現在正在添加一個新的算法。 – AlQafir

0

一個小的通用方法是實現一個發生器適配器來過濾發生器。然後,您可以以任何您想要的方式輕鬆實現謂詞。在這裏我使用vector,但set可以做得很好,並可能提供更好的性能。

隨機發生器由TR1C++11隨機設施提供。

#include <set> 
#include <algorithm> 
#include <vector> 
#include <iostream> 
#include <random> 
#include <cstdint> 
#include <functional> 

template<typename Generator, typename Predicate> 
struct filtered_generator { 
    Generator g; 
    Predicate p; 

    auto operator()() -> decltype(g()) { 
    auto tmp = g(); 
    if(p(tmp)) 
     return tmp; 
    else 
     return (*this)(); 
    } 
}; 

template<typename G, typename P> 
filtered_generator<G, P> make_filter(const G& g, const P& p) { 
    return filtered_generator<G, P>{g, p}; 
} 

int main() 
{ 
    std::mt19937 eng; 
    eng.seed(23); 
    std::uniform_int_distribution<std::uint8_t> dist(1, 10); 
    auto rnd = std::bind(dist, eng); 

    { 
    // using a vector 
    std::vector<uint8_t> forbidden = {1, 2, 3}; 
    auto g = make_filter(rnd, [&forbidden](std::uint8_t t) { 
    return std::find(forbidden.begin(), forbidden.end(), t) == forbidden.end(); 
    }); 

    for(int i = 0; i < 20; ++i) 
    { 
     std::cout << static_cast<int>(g()) << std::endl; 
    } 
    } 

    // using a set 
    std::set<std::uint8_t> forbidden = {1, 2, 3}; 
    auto g = make_filter(rnd, [&forbidden](std::uint8_t t) { 
    return forbidden.count(t) == 0; 
    }); 

for(int i = 0; i < 20; ++i) 
{ 
    std::cout << static_cast<int>(g()) << std::endl; 
} 
} 

當發電機提供 一個result_type的typedef,以消除decltype的依賴和 lambda表達式將不得不進入仿函數C++ 03的適應應該是容易實現。