如何生成8位(伪)随机数,以便排除某些已知数字

How do I generate 8 bit (pseudo) random numbers so that I exclude certain known numbers?

本文关键字:排除 数字 8位 何生成 随机数      更新时间:2023-10-16

我想生成8位(uint8_t)随机数,以便我排除一组已经指定的众所周知的数字。基本上从0x00到0xFF的数字,但我有一些数字在这个范围内,我不想出现。

我正在考虑用允许的数字填充一个向量,并选择一个(伪)随机索引并使用该索引。

我怀疑他们可能有严重的缺点,所以寻找线索/建议。解决方案不需要是火箭科学级别,但只要足够简单,"看起来"随机:)

编辑:我不想使用像boost这样的外部库,因为我正在开发ARM嵌入式解决方案

编辑:我不支持c++ 11

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数组来禁用任何数字。

#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的解决方案快一点。

一种较小的通用方法是实现一个过滤Generator的Generator适配器。然后,您可以轻松地以您想要的任何方式实现谓词。这里我使用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;
 }
}

当生成器提供时,c++ 03适配应该很容易实现一个result_type类型定义来移除对decltype的依赖而lambda必须变成函子