是否存在可随机访问的伪随机数生成器之类的东西?(最好是开源的)

StackOverflow https://stackoverflow.com/questions/3019169

  •  26-09-2019
  •  | 
  •  

首先,是否存在随机访问随机数生成器之类的东西,您不仅可以像我们习惯的那样顺序生成随机数,假设 rand100() 始终生成 0-100 之间的值:

for (int i=0;i<5;i++)
   print rand100()

output: 
14
75
36
22
67

还可以随机访问任何随机值,例如:

只要您不更改种子,Rand100(0)就会输出14

rand100(3)总是输出22

rand100(4)将始终输出67

等等...

我实际上找到了一个开源生成器算法可以做到这一点,但你无法更改种子。我知道伪随机性是一个复杂的领域;我不知道如何改变它来添加该功能。

是否有可播种的随机访问随机数生成器,最好是开源的?或者有更好的术语,我可以通过谷歌搜索更多信息吗?

如果没有,我的问题的第二部分是,是否有任何可靠的随机开源传统可种子伪随机数生成器,以便我可以将其移植到多个平台/语言,同时为任何给定种子的每个平台保留一致的值序列?

有帮助吗?

解决方案

PCG家庭伪随机数发生器的可以跳向前和向后以对数时间(即向前抬至1000号需要O(日志(1000))操作),这可能是要考虑的随机存取不够好。参考C和C ++实现都支持这种功能。

盈科网站的头版,该表显示,其他一些发电机可以支持跳跃前进,但我没有任何实现见过它。

其他提示

我没有听说过这样的事情,但在我看来,你可能需要使用一个体面的哈希值,并编写一个包装函数,它的种子值和你的“索引”,并运行他们通过哈希函数。我不知道通过各种加密散列函数输出的比特的随机性的,但我想有人已经采取了看那个。

百隆百隆莎布是一个伪随机数发生器以种子和随机存取的任何值它产生

感谢您的所有答复,也感谢任何可能在此提出类似问题时发生的任何人,我找到了一个解决方案,这不是我所要求的,但适合我的目的。

它是一个 柏林噪声 可以找到的类 这里。我不确定这相对于传统的随机数生成器来说计算复杂度如何,这是一个问题,因为计划的平台之一是 Android。此外,柏林噪声与伪随机性不同,但据我所知,高倍频程和/或频率值应该为非加密目的提供合适的随机性,其中真正随机性的统计水平并不那么重要仅仅是随机性的表现。

该解决方案允许播种,并且还允许从任意点对随机集进行采样,换句话说,随机访问随机性。

下面是左列中用于比较的常规 C++ 随机性 (rand%200) 示例集,右列是柏林噪声(相当于 %200):

91 , 100
48 , 97
5 , 90
93 , 76
197 , 100
97 , 114
132 , 46
190 , 67
118 , 103
78 , 96
143 , 110
187 , 108
139 , 79
69 , 58
156 , 81
123 , 128
84 , 98
15 , 105
178 , 117
10 , 82
13 , 110
182 , 56
10 , 96
144 , 64
133 , 105

两者的种子都为 0

柏林噪声的参数是

octaves = 8
amplitude = 100 
frequency = 9999
width/height = 10000,100

柏林噪声的顺序采样顺序很简单

for (int i=0;i<24;i++)
    floor(Get(i,i)+100);
//amplitude 100 generates noise between -100 and 100, 
//so adding 100 generates between 0 and 200

在我读谁使用在谷歌,这回答了你的差不多问题工作的人一个很好的博客文章。

在短,答案是使用块密码用随机数作为加密密钥,并且你的序列中要用作要加密的数据的数目的索引。他提到一个密码,可以在任何大小的块工作(位),这是方便 - 我不得不搜索博客找到密码的名称

例如:假设您想整数从0到(2 ^ 32)-1的随机洗牌。可以实现,使用一个块密码,其需要4个字节的输入,并返回4个加密字节。遍历系列,第一个“加密”的值为0的块,则1,则2等如果只希望在所述混洗序列的第百万项,则只是加密数百万。

在“随机序列”,你会得到使用的密码是从你会得到使用哈希函数是什么(如@MichaelBurr建议)不同。使用密码,你可以得到的随机排列的整数范围,并在不断的时间排列品尝任何项目。换句话说,在“随机数”不会重复。如果使用一个散列函数,该序列中的号码可以重复。

说了这么多,@ MichaelBurr的解决方案更适合您的情况,我建议你使用它。

实现这一目标的一种方法是从较小的集合中合成大量的随机数据。一种方法是使用三个预先生成的随机数据数组。每个数组应该有素数个整体。

为了产生我们的随机数,我们想象这些一次性填充中的每一个都被无限循环并增量采样;我们使用异或组合每个数据。

#define PRIME1 7001
#define PRIME2 7013
#define PRIME3 7019

static int pad1[PRIME1];
static int pad2[PRIME2];
static int pad3[PRIME3];

static void random_no_init (void)
{
  static int initialized = 0;
  int i;
  if (initialized)
    return;
  for (i = 0; i < PRIME1; i++) pad1[i] = random ();
  for (i = 0; i < PRIME2; i++) pad2[i] = random ();
  for (i = 0; i < PRIME3; i++) pad3[i] = random ();

  initialized = 1;
}

int random_no (int no)
{
   random_no_init ();
   return pad1[no % PRIME1] ^ pad2[no % PRIME2] ^ pad3[no % PRIME3];
}

上面的代码示例显示了一个简单的示例,它生成 344618953247 个可随机访问的整体。为了确保运行之间的结果可重现,您应该提供带有种子的随机数生成器。可以在以下位置找到基于相同原理构建的更复杂的系统,其种子变化基于选择不同的素数 http://git.gnome.org/browse/gegl/tree/gegl/gegl-random.c

所有我知道的发电机迭代。所以,任何“随机访问”将涉及计算从第一所有的值给你索要一个。

你能来最接近的是采取一个固定的种子,散,然后散列索引值,使用的东西,真正的混音热情。

或者生成它们的长列表和存储。

看一看本专利: 随机存取的伪随机数生成器 https://patents.google.com/patent/US4791594

它采用多级比特加扰方案来产生伪数序列,其能够被随机访问。

我们的想法是使用输入地址作为控制位,以加扰的多个种子数,然后XOR结果来产生一个输出,然后使用来自先前轮次中产生的结果加扰的第二遍。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top