Sqlite 生成随机数序列的简单函数,不知道以前的数字,但知道当前索引(无变量赋值)?

Sqlite 生成随机数序列的简单函数,不知道以前的数字,但知道当前索引(无变量赋值)?,sqlite,optimization,random,language-agnostic,seed,Sqlite,Optimization,Random,Language Agnostic,Seed,是否有任何(简单的)随机生成函数可以在没有变量赋值的情况下工作?我读到的大多数函数都是这样的current=next(current)。然而,目前我有一个限制(来自SQLite),我不能使用任何变量 是否有方法仅使用n(序列中的当前数字索引)和种子生成数字序列(例如,从1到max) 目前我使用的是: cast((1103515245*Seed*ROWID+12345)%2147483648)/2147483648.0*Max as int)+1 max为47,ROWID为n。然而,对于某些种子,

是否有任何(简单的)随机生成函数可以在没有变量赋值的情况下工作?我读到的大多数函数都是这样的
current=next(current)
。然而,目前我有一个限制(来自SQLite),我不能使用任何变量

是否有方法仅使用
n
(序列中的当前数字索引)和
种子生成数字序列(例如,从1到
max

目前我使用的是:

cast((1103515245*Seed*ROWID+12345)%2147483648)/2147483648.0*Max as int)+1

max
为47,
ROWID
n
。然而,对于某些种子,重复率太高(47个种子中有3个是唯一的)

在我的要求中,重复是可以的,只要它不是太多(A加上(A,c和m模)将是一个完整的周期生成器,因此在重复之前,它会伪随机地循环其周期中的每个整数。虽然您以前可能尝试过这个想法,但您是否认为m在您的情况下等同于
max
?有关此类生成器的参数选择列表,请参阅L'Ecuyer,第页。,“不同尺寸和良好晶格结构的线性同余发生器表”,《计算数学》68(225),1999年1月

请注意,在SQLite中实现这一点存在一些实际问题,特别是当您的SQLite版本仅支持32位整数和64位浮点数(精度为52位)时-

  • 如果整数的中间乘法超过32位,则溢出,并且
  • 如果中间乘法导致大于52位的数字,则会导致精度损失

也要考虑为什么要创建随机数序列:

  • 序列是不可预测的吗?在这种情况下,仅使用线性同余生成器是不够的,您应该通过其他方式(例如通过)生成唯一标识符
  • 以这种方式生成的数字会以任何方式向最终用户公开吗?如果不会,就没有必要通过“洗牌”来混淆它们
此外,根据您正在使用的SQLite API(用于您的编程语言),可能有一种方法可以编写自定义函数,将种子和
ROWID
转换为随机唯一数。但是,详细信息在很大程度上取决于特定的SQLite API。显示了Perl的一个示例。

a和(a、c和m)将是一个完整的周期生成器,因此在重复之前,它会伪随机地循环其周期中的每个整数。虽然您以前可能尝试过这个想法,但您是否考虑过在您的情况下m等同于
max
?有关此类生成器的参数选择列表,请参阅L'Ecuyer,P.“不同尺寸和良好晶格结构的线性同余发生器表”,计算数学68(225),1999年1月

请注意,在SQLite中实现这一点存在一些实际问题,特别是当您的SQLite版本仅支持32位整数和64位浮点数(精度为52位)时-

  • 如果整数的中间乘法超过32位,则溢出,并且
  • 如果中间乘法导致大于52位的数字,则会导致精度损失

也要考虑为什么要创建随机数序列:

  • 序列是不可预测的吗?在这种情况下,仅使用线性同余生成器是不够的,您应该通过其他方式(例如通过)生成唯一标识符
  • 以这种方式生成的数字会以任何方式向最终用户公开吗?如果不会,就没有必要通过“洗牌”来混淆它们

另外,根据您使用的SQLite API(用于您的编程语言),可能有一种方法可以编写自定义函数来将种子和
ROWID
转换为随机唯一数。但是,详细信息在很大程度上取决于特定的SQLite API。显示了一个Perl示例。

如何使用好的哈希函数并将结果映射到[1…max]范围

沿着这条路线(伪代码)。
sha1
被添加到SQLite 3.17中

sha1(ROWID) % Max + 1

或者使用任何外部C代码进行散列(杂音,chacha,…),如图所示

如何使用良好的散列函数并将结果映射到[1…max]范围

沿着这条路线(伪代码)。
sha1
被添加到SQLite 3.17中

sha1(ROWID) % Max + 1

或者使用任何外部C代码进行散列(杂音,chacha,…),如图所示

我不确定您是否仍然存在相同的问题,但我可能有一个解决方案。 你可以使用基于移位寄存器的伪随机M序列生成器,你只需要对原始多项式取足够高的阶,而不需要存储任何变量。 有关更多信息,请查看

您需要编写的只是原始多项式移位方程,我在一个在线编辑器中检查过,这应该很容易做到。我认为最简单的方法是使用二进制基数和PRBS序列,并根据您将拥有的元素数量选择序列长度。例如,这是imple对于长度为
2^15=32768
(PRBS15)的原始多项式,我从wiki页面上获取(在那里你可以找到原始多项式,一直到PRBS31,即
2^31=2.1475e+09
) 基本上,您需要做的是:

SELECT(((ROWID>14)(ROWID>13))&1))&0x7fff)
这种方法的美妙之处在于,如果您采用的PRB序列的周期比您的ROWID最大值长,那么您将拥有唯一的随机索引。非常简单。:)

如果您需要有关搜索原始多项式的帮助,可以查看我的