【问题标题】:How do I generate 8 bit (pseudo) random numbers so that I exclude certain known numbers?如何生成 8 位(伪)随机数以便排除某些已知数字?
【发布时间】:2011-11-19 12:35:54
【问题描述】:

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

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

我怀疑他们在这方面可能存在严重缺陷,因此请寻求线索/建议。解决方案不必是火箭科学级别,只要简单到“出现”随机即可:)

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

编辑:我不支持 C++11

【问题讨论】:

  • 您的解决方案对我来说听起来不错。去吧。 (不确定这是否应该是答案或评论,但实际上没有什么可添加的;从数组中选择随机元素总是发生......)
  • +1 这是一种常用的方法来选择具有禁止值的随机数。
  • 如果你的禁用数字列表在运行时没有改变,并且如果 256 字节对你来说不是很多内存,那么我会说你是最好的解决方案。
  • @TonyK - 是的,它不会改变,它是 256 字节内存是可以容忍的内存

标签: c++ random


【解决方案1】:
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 数组进行操作来禁用任何您想要的数字。

【讨论】:

  • 预期的运行时间是多少? :-)
  • 这不会有一个非常令人满意的统计分布。
  • 我的算法很慢,但是当他问简单的代码时,什么会更简单?此外,由于可接受结果的范围仅为 256,因此不需要的大数组会使其无法使用。我现在正在添加一个新算法..
  • 我喜欢这个。这确实是我正在使用的小范围,这很适合我,尤其是您的第二次编辑
【解决方案2】:
#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 的解决方案快一点。

【讨论】:

  • 是的,使用更大的exclude 数组确实更快。由于他要处理一小部分数字,我还添加了一个新算法,每个数字只执行一次检查。
  • 哦!事件更好。塔。会试试这个和我自己的建议
  • 得到错误:algorithm: No such file or directory
【解决方案3】:

一个小的通用方法是实现一个过滤生成器的生成器适配器。然后,您可以轻松地以任何您想要的方式实现谓词。这里我使用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 typedef 来删除对decltype 的依赖,并且 lambdas 必须进入函子。

【讨论】:

    猜你喜欢
    • 2015-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-07
    • 1970-01-01
    • 2013-02-02
    • 1970-01-01
    • 2014-10-30
    相关资源
    最近更新 更多