命名的一致随机数范围

背景

接下来的一个问题是,我刚才问了一些关于如何得到一组不同的(但不一定是唯一的)随机数的答案:

=RANDBETWEEN(ROW(A1:A10)^0,10) 

获得1到10之间的10个随机数的数组

问题

如果我用上面的公式创build一个命名的范围(称为“randArray”),我希望我能够引用randArray许多次,并获得相同的随机数集。 当然,他们会改变每次我按F9或更新工作表 – 但一起改变。

这就是我所得到的,是两组完全不同的随机数

在这里输入图像描述

我对这种行为并不感到惊讶,但是如何在不使用VBA的情况下实现这一点, 也不需要将随机数字放在工作表上


如果你有兴趣

这个例子旨在成为MCVE。 在我的实际情况中,我使用随机数来估计Pi。 用户规定应用多less个随机点并得到相应的准确估计。 出现这个问题的原因是我也绘制点,当有less量的点时,很清楚的是看到估计和图不代表相同的数据集


更新

我已经把@Michael的最初奖金授予了一个有趣和不同的解决scheme。 我仍在寻找一个完整的解决scheme,允许用户规定使用多less个随机点,虽然可能没有一个完美的答案,但我仍然对其他任何可能的解决scheme感兴趣,并且乐于提供更多的奖励。

感谢迄今为止所做的贡献。

好的,这里有一个解决scheme,用户可以在定义的名称SAMPLESIZE指定数值

 =MOD(ROUND(MOD(ROUND(NOW()+ROW(OFFSET(INDIRECT("A1"),0,0,SampleSize)),4)*10000*163,1013),0)+ROUND(MOD(ROUND(NOW()+ROW(OFFSET(INDIRECT("A1"),0,0,SampleSize))*2,4)*10000*211,1013),0)+ROUND(MOD(ROUND(NOW()+ROW(OFFSET(INDIRECT("A1"),0,0,SampleSize))*3,4)*10000*17,1013),0)+ROUND(MOD(ROUND(NOW()+ROW(OFFSET(INDIRECT("A1"),0,0,SampleSize))*5,4)*10000*179,53),0)+ROUND(MOD(ROUND(NOW()+ROW(OFFSET(INDIRECT("A1"),0,0,SampleSize))*7,4)*10000*6101,1013),0),10)+1 

这是一个很长的公式,但效率很高,可用于其他function。 试图在一个较短的公式导致无法很好的performance和数组,由于某种原因不能用于其他function。

这个解决scheme结合了5个不同的素数生成器来增加生成的随机数的种类。 引入了一些任意常量来减less重复模式。

这有正确的分配和相当好的随机性。 样本量为10,000的重复testing导致个体数字的频率在960和1040之间变化,没有总体偏好。 但是,它似乎有连续两次产生相同数字的奇怪特性!

这个解决scheme产生10个看似10到10之间的随机数,每次持续近9秒。 这允许同一公式的重复调用在单次刷新中返回相同的一组值。

如果需要,您可以修改时间范围。 更短的时间段允许更频繁的更新,但是也略微增加了在切换点之后发生一些对公式的调用的极不可能的机会,从而导致第二组10个随机数用于随后的调用。

首先,用10个不同的素数定义一个数组“Primes”:

 ={157;163;167;173;179;181;191;193;197;199} 

然后,定义这个公式,将返回一个10个随机数组的数组:

 =MOD(ROUND(MOD(ROUND(NOW(),4)*70000,Primes),0),10)+1 

说明:

我们需要build立我们自己的随机数发生器,我们可以用相同的数值种子一段时间; 足够长的时间让所谓的公式继续返回相同的值。

首先,我们创build一个种子: ROUND(NOW(),4)每0.0001天= 8.64秒创build一个新的种子数。

我们可以使用下面的公式生成粗略的随机数:

Random = Seed * 7 mod Prime

https://cdsmith.wordpress.com/2011/10/10/build-your-own-simple-random-numbers/

理想情况下,通过从前一个输出中获取input来生成一个随机数序列,但是我们不能在单个函数中完成这个操作。 所以相反,这使用了10个不同的素数,实质上是启动了10个不同的随机数生成器。 现在,随机数的生成可靠性较低,但下面的testing结果显示,它似乎做得相当不错。

ROUND(NOW(),4)*70000使我们的种子达到一个整数,并同时乘以7

MOD(ROUND(NOW(),4)*70000,Prime)生成从0到相应素数的10个随机数序列

ROUND(MOD(ROUND(NOW(),4)*70000,Prime),0)需要我们回到一个整数,因为Excel似乎很难将Mod应用于浮点数。

=MOD(ROUND(MOD(ROUND(NOW(),4)*70000,Prime),0),10)+1只取从那个地方的值(从0到9的随机数)并移动它给我们一个从1到10的随机数

testing结果:

我生成了500个10个随机数(以列而不是行)为单位,对于种子值递增0.0001,并计算每个素数的每个数字出现的次数。 你可以看到每个数字总共发生了近500次,每个素数之间每个数字的分布几乎相等。 所以,这可能适合你的目的。

看看立即连续产生的数字,你可以看到相邻的素数之间的相似性,他们不完全相同,但是他们在地方非常接近,即使他们偏移了几行。 但是,如果刷新以随机间隔发生,您仍然会看到随机数字,这应该足够您的目的。 否则,您仍然可以将此方法应用于更复杂的随机数生成器,或尝试不同的素数进一步分离。

结果

更新1:试图find一种能够指定生成的随机数的数量,而不存储素数列表。

尝试1:使用具有种子数组的单个素数:

 =MOD(ROUND(MOD(ROUND(NOW()+ROW(OFFSET(INDIRECT("A1"),0,0,SampleSize))/10000,4)*70000,1013),0),10)+1 

这确实给你一个均匀分布,但它实际上只是重复10个数字完全相同的序列。 对样本的任何分析都将与分析=MOD(ROW(1:SampleSize),10)+1 。 我想你想要更多的变化!

尝试2:仍然使用10个素数的二维数组…

更新2:没有工作。 performance糟糕。 已经提交了一个新的答案,采取了类似但不同的方法。

这不是一个好的答案,但是考虑到volatile函数的局限性,使用带有volatile函数的IF公式和一个放置在工作表某处的volatilevariables是一个可能的答案。

我用下面的公式来达到预期的效果

 =IF(rngIsVolatile,randArray,A1:A10) 

我设置单元格B12为rngIsVolatile。 我粘贴下面的截图看看它在工作。

IF公式来限制挥发性功能的波动性

当rngIsVolatile设置为True时,它从randArray中获取新值: 易失性函数结果#01

当rngIsVolatile设置为False时,它从A1:A10中提取旧值: 易失性函数结果#02