提问人:Luke Vo 提问时间:5/15/2019 最后编辑:Luke Vo 更新时间:2/7/2020 访问量:272
在不知道前一个数字但知道当前索引(无变量赋值)的情况下生成随机数序列的简单函数?
Simple function to generate random number sequence without knowing previous number but know current index (no variable assignment)?
问:
是否有任何(简单的)随机生成函数可以在没有变量赋值的情况下工作?我读到的大多数函数都是这样的。但是,目前我有一个限制(来自SQLite),我根本不能使用任何变量。current = next(current)
有没有办法生成一个数字序列(例如,从 1 到 ),只有(序列中的当前数字索引)和?max
n
seed
目前我正在使用它:
cast(((1103515245 * Seed * ROWID + 12345) % 2147483648) / 2147483648.0 * Max as int) + 1
随着 47 岁,是 .然而,对于某些种子来说,重复率太高(47 颗种子中有 3 颗)。max
ROWID
n
在我的要求中,只要不是太多(<50%),重复就可以了。有没有更好的功能可以满足我的需求?
该问题有sqlite标签,但任何语言/伪代码都可以。
P.s:我尝试过将线性同余生成器与一些 a/c/m 三元组和 as 一起使用,但它效果不佳,甚至更糟。Seed * ROWID
Seed
编辑:我目前使用这个,但我不知道它来自哪里。价格看起来比我的好:
((((Seed * ROWID) % 79) * 53) % "Max") + 1
答:
具有适当选择参数(a、c 和模数 m)的线性同余生成器将是一个全周期生成器,因此它在重复之前伪随机循环其周期内的每个整数。虽然你以前可能尝试过这个想法,但你有没有考虑过 m 等价于你的情况?有关此类生成器的参数选择列表,请参见 L'Ecuyer, P., “Tables of Linear Congruential Generators of Different Sizes and Good Lattice Structure”, Mathematics of Computation 68(225),1999 年 1 月。max
请注意,在 SQLite 中实现这一点存在一些实际问题,特别是如果您的 SQLite 版本仅支持 32 位整数和 64 位浮点数(精度为 52 位)。也就是说,可能存在以下风险:
- 如果整数的中间乘法超过 32 位,则溢出,并且
- 如果中间乘法导致大于 52 位的数字,则精度损失。
另外,请考虑为什么要创建随机数序列:
- 序列是否具有不可预测性?在这种情况下,仅使用线性全等生成器是不够的,您应该通过其他方式生成唯一标识符,例如将唯一数字与加密随机数组合在一起。
- 以这种方式生成的数字是否会以任何方式暴露给最终用户?如果没有,则无需通过“洗牌”来混淆它们。
此外,根据您使用的 SQLite API(适用于您的编程语言),可能有一种方法可以编写自定义函数来将种子转换为随机唯一数。但是,细节很大程度上取决于特定的SQLite API。另一个答案显示了 Perl 的示例。ROWID
评论
max
ROWID
ROWID
使用良好的哈希函数并将结果映射到 [1...max] 范围怎么样?
沿着这条线(在伪代码中)。 已添加到 SQLite 3.17。sha1
sha1(ROWID) % Max + 1
或者使用任何外部 C 代码进行哈希(murmur、chacha 等),如下所示
评论
sqlite_version()
我不确定你是否还有同样的问题,但我可能会为你找到一个解决方案。 您可以做的是使用基于移位寄存器的伪随机 M 序列生成器。你只需要取足够高的原始多项式的阶数,你不需要真正存储任何变量。 有关更多信息,您可以查看 wiki 页面
您需要编写的只是原始多项式移位方程,我已经在在线编辑器中检查过,它应该很容易做到。我认为最简单的方法是使用二进制基础并使用 PRBS 序列,并且根据您将拥有的元素数量,您可以选择序列长度。例如,这是我从 wiki 页面获取的原始多项式 (PRBS15) 长度的实现(在那里你可以找到一直到 PRBS31 的原始多项式)
基本上你需要做的是:2^15 = 32768
2^31=2.1475e+09
SELECT (((ROWID << 1) | (((ROWID >> 14) <> (ROWID >> 13)) & 1)) & 0x7fff)
这种方法的优点是,如果采用周期长于ROWID最大值的PRBS序列,则将具有唯一的随机索引。很简单。:)
如果你在搜索原始多项式时需要帮助,你可以看看我的 github 存储库,它完全处理如何查找原始多项式和唯一的 m 序列。它目前是用 Matlab 编写的,但我计划在未来几天内用 python 编写它。
干杯!
评论
random()
Seed