返回很大范围内的非重复随机值

2024-02-20

我想要一个函数,它可以从一组 n 个整数(0 到 n-1)中生成 k 个伪随机值,而不重复任何先前的结果。 k小于或等于n。O(n) 内存不可接受由于尺寸较大n以及我需要重新洗牌的频率。

这些是我到目前为止考虑过的方法:

Array: 通常,如果我想要无重复的随机值,我会打乱数组,但这是 O(n) 内存。 n 可能太大而无法正常工作。

long nextvalue(void) {
  static long array[4000000000];
  static int s = 0;
  if (s == 0) {
    for (int i = 0; i < 4000000000; i++) array[i] = i;
    shuffle(array, 4000000000);
  }
  return array[s++];
}

n态PRNG: 有多种随机数生成器,可以将其设计为具有以下周期:n并参观n那个时期的独特状态。最简单的例子是:

long nextvalue(void) {
static long s = 0;
static const long i = 1009; // assumed co-prime to n
  s = (s + i) % n;
  return s;
}

这样做的问题是,对于给定的情况,动态设计一个好的 PRNG 并不一定容易。n,如果 PRNG 没有很多可变参数(甚至更难设计),它就不太可能近似公平的洗牌。但也许有一个我不知道的好东西。

m位哈希: 如果集合的大小是 2 的幂,那么就有可能设计出完美的哈希函数f()它执行从范围内的任何值到范围内的某个其他值的 1:1 映射,其中每个输入都会产生唯一的输出。使用这个函数我可以简单地维护一个静态计数器s,并将生成器实现为:

long nextvalue(void) {
  static long s = 0;
  return f(s++);
}

这并不理想,因为结果的顺序由以下因素决定f(),而不是随机值,因此它会遇到与上述相同的问题。

NPOT 哈希: 原则上我可以使用与上面相同的设计原则来定义一个版本f()它可以在任意基础上工作,甚至可以在与所需范围兼容的复合基础上工作;但这可能很困难,而且我很可能会出错。相反,可以为大于或等于的下一个二的幂定义一个函数n,并在此结构中使用:

long nextvalue(void) {
  static long s = 0;
  long x = s++;
  do { x = f(x); } while (x >= n);
}

但是这个still有同样的问题(不太可能给出公平洗牌的良好近似值)。

有没有更好的方法来处理这种情况?或者也许我只需要一个好的功能f()高度参数化且易于设计以准确访问n离散状态。

我正在考虑的一件事是类似哈希的操作,我设法获得第一个j通过精心设计的映射,结果完全随机,然后之间的任何结果j and k会简单地推断该模式(尽管以可预测的方式)。价值j然后可以选择在公平洗牌和可容忍的内存占用之间找到折衷方案。


首先,对任何使用 O(n) 内存的东西打折扣,然后讨论引用底层数组的解决方案似乎是不合理的。你有一个数组。洗牌。如果这不起作用或不够快,请向我们提出相关问题。

您只需执行一次完整的随机播放。之后,从索引中提取n,将该元素与随机位于其之前的元素交换并增加n,模元素计数。例如,对于如此大的数据集,我会使用像这样的东西 https://gist.github.com/Sebbyastian/40be860d95f9df95f319a2f17dc74dde.

质数是哈希的一种选择,但可能与您想象的不同。使用两个梅森素数 (low and high, 也许0xefff and 0xefffffff)你应该能够想出一个更通用的哈希算法。

size_t hash(unsigned char *value, size_t value_size, size_t low, size_t high) {
    size_t x = 0;
    while (value_size--) {
        x += *value++;
        x *= low;
    }
    return x % high;
}
#define hash(value, value_size, low, high) (hash((void *) value, value_size, low, high))

例如,对于大于大约两个八位位组的所有输入,这应该产生相当好的分布,但零字节前缀有一个小麻烦的例外。您可能想以不同的方式对待它们。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

返回很大范围内的非重复随机值 的相关文章

  • EF Core Group By 翻译支持条件总和

    听说 EF Core 2 1 将支持翻译小组 我感到非常兴奋 我下载了预览版并开始测试它 但发现我在很多地方仍然没有得到翻译分组 在下面的代码片段中 对 TotalFlagCases 的查询将阻止翻译分组工作 无论如何 我可以重写这个以便我
  • “构建”构建我的项目,“构建解决方案”则不构建

    我刚刚开始使用VS2010 我有一个较大的解决方案 已从 VS2008 成功迁移 我已将一个名为 Test 的控制台应用程序项目添加到解决方案中 选择构建 gt 构建解决方案不编译新项目 选择构建 gt 构建测试确实构建了项目 在失败的情况
  • 以文化中立的方式将字符串拆分为单词

    我提出了下面的方法 旨在将可变长度的文本拆分为单词数组 以进行进一步的全文索引处理 删除停止词 然后进行词干分析 结果似乎不错 但我想听听关于这种实现对于不同语言的文本的可靠性的意见 您会建议使用正则表达式来代替吗 请注意 我选择不使用 S
  • 在哪里可以找到列出 SSE 内在函数操作的官方参考资料?

    是否有官方参考列出了 GCC 的 SSE 内部函数的操作 即 头文件中的函数 除了 Intel 的 vol 2 PDF 手册外 还有一个在线内在指南 https www intel com content www us en docs in
  • Asp.NET WebApi 中类似文件名称的路由

    是否可以在 ASP NET Web API 路由配置中添加一条路由 以允许处理看起来有点像文件名的 URL 我尝试添加以下条目WebApiConfig Register 但这不起作用 使用 URIapi foo 0de7ebfa 3a55
  • 不同枚举类型的范围和可转换性

    在什么条件下可以从一种枚举类型转换为另一种枚举类型 让我们考虑以下代码 include
  • 将 VSIX 功能添加到 C# 类库

    我有一个现有的单文件生成器 位于 C 类库中 如何将 VSIX 项目级功能添加到此项目 最终目标是编译我的类库项目并获得 VSIX 我实际上是在回答我自己的问题 这与Visual Studio 2017 中的单文件生成器更改 https s
  • 创建链表而不将节点声明为指针

    我已经在谷歌和一些教科书上搜索了很长一段时间 我似乎无法理解为什么在构建链表时 节点需要是指针 例如 如果我有一个节点定义为 typedef struct Node int value struct Node next Node 为什么为了
  • 将多个表映射到实体框架中的单个实体类

    我正在开发一个旧数据库 该数据库有 2 个具有 1 1 关系的表 目前 我为每个定义的表定义了一种类型 1Test 1Result 我想将这些特定的表合并到一个类中 当前的类型如下所示 public class Result public
  • 重载<<的返回值

    include
  • 转发声明和包含

    在使用库时 无论是我自己的还是外部的 都有很多带有前向声明的类 根据情况 相同的类也包含在内 当我使用某个类时 我需要知道该类使用的某些对象是前向声明的还是 include d 原因是我想知道是否应该包含两个标题还是只包含一个标题 现在我知
  • 使用 x509 证书签署 json 文档或字符串

    如何使用 x509 证书签署 json 文档或字符串 public static void fund string filePath C Users VIKAS Desktop Data xml Read the file XmlDocum
  • 覆盖子类中的字段或属性

    我有一个抽象基类 我想声明一个字段或属性 该字段或属性在从该父类继承的每个类中具有不同的值 我想在基类中定义它 以便我可以在基类方法中引用它 例如覆盖 ToString 来表示 此对象的类型为 property field 我有三种方法可以
  • 如何使用 C# / .Net 将文件列表从 AWS S3 下载到我的设备?

    我希望下载存储在 S3 中的多个图像 但目前如果我只能下载一个就足够了 我有对象路径的信息 当我运行以下代码时 出现此错误 遇到错误 消息 读取对象时 访问被拒绝 我首先做一个亚马逊S3客户端基于我的密钥和访问配置的对象连接到服务器 然后创
  • 对现有视频添加水印

    我正在寻找一种用 C 在视频上加水印的方法 就像在上面写文字一样 图片或文字标签 我该怎么做 谢谢 您可以使用 Nreco 视频转换器 代码看起来像 NReco VideoConverter FFMpegConverter wrap new
  • 向现有 TCP 和 UDP 代码添加 SSL 支持?

    这是我的问题 现在我有一个 Linux 服务器应用程序 使用 C gcc 编写 它与 Windows C 客户端应用程序 Visual Studio 9 Qt 4 5 进行通信 是什么very在不完全破坏现有协议的情况下向双方添加 SSL
  • 将控制台重定向到 .NET 程序中的字符串

    如何重定向写入控制台的任何内容以写入字符串 对于您自己的流程 Console SetOut http msdn microsoft com en us library system console setout aspx并将其重定向到构建在
  • 是否可以在 .NET Core 中将 gRPC 与 HTTP/1.1 结合使用?

    我有两个网络服务 gRPC 客户端和 gRPC 服务器 服务器是用 NET Core编写的 然而 客户端是托管在 IIS 8 5 上的 NET Framework 4 7 2 Web 应用程序 所以它只支持HTTP 1 1 https le
  • 哪种 C 数据类型可以表示 40 位二进制数?

    我需要表示一个40位的二进制数 应该使用哪种 C 数据类型来处理这个问题 如果您使用的是 C99 或 C11 兼容编译器 则使用int least64 t以获得最大的兼容性 或者 如果您想要无符号类型 uint least64 t 这些都定
  • C++ 标准是否指定了编译器的 STL 实现细节?

    在写答案时this https stackoverflow com questions 30909296 can you put a pimpl class inside a vector我遇到了一个有趣的情况 这个问题演示了这样一种情况

随机推荐