命名范围的一致随机数

时间:2017-03-16 13:46:23

标签: arrays excel random excel-formula

背景

question I asked a while ago关于获得一系列不同(但不一定是唯一的)随机数的答案是这样的:

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

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

问题

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

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

enter image description here

我对此行为并不感到惊讶,但如何在不使用VBA且不将随机数放入工作表的情况下实现

<小时/> 如果您有兴趣

此示例旨在成为MCVE。在我的实际情况中,我使用随机数来估计Pi。用户规定要应用多少随机点并获得相应准确的估计。之所以出现这个问题,是因为我也对点进行了绘制,当有少量点时,很清楚地看到估计和图形不代表相同的数据集

更新

我已将最初的赏金授予@Michael提供有趣且不同的解决方案。我仍然在寻找一个完整的解决方案,允许用户规定使用多少随机点,虽然可能没有完美的答案,但我仍然对任何其他可能的解决方案感兴趣,并且非常乐意进一步提供奖励。

感谢迄今为止贡献的所有人。

3 个答案:

答案 0 :(得分:2)

此解决方案生成10个看似随机的数字,介于1和10之间,一次持续近9秒。这允许重复调用相同的公式,以在单次刷新中返回相同的值集。

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

首先,定义一个阵列&#34; Primes&#34;有10个不同的素数:

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

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

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

说明:

我们需要建立自己的随机数生成器,我们可以在一段时间内使用相同的值播种;足够长的时间让被调用的公式保持返回相同的值。

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

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

Random = Seed * 7 mod Prime

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

理想情况下,通过从前一个输出中获取输入来生成一系列随机数,但我们无法在单个函数中执行此操作。因此,它使用10个不同的素数,基本上启动了10个不同的随机数生成器。现在,这在生成随机数时的可靠性较低,但下面的测试结果表明它实际上似乎做得非常好。

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的随机数

测试结果:

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

查看即时连续生成的数字,您可以看到相邻素数之间的相似性,它们并不完全相同,但它们在某些地方非常接近,即使它们被一个地方抵消了几行。但是,如果刷新是以随机间隔进行的,那么您仍然可以获得看似随机的数字,这应该足以满足您的需要。否则,您仍然可以将此方法应用于更复杂的随机数生成器,或者尝试使用更远的素数的不同混合。

Results

更新1:试图找到一种方法,可以指定生成的随机数的数量,而无需存储素数列表。

尝试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:没有工作。它表现糟糕。提交的新答案采用了类似但不同的方法。

答案 1 :(得分:1)

好的,这是一个解决方案,用户可以使用指定名称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

它是一个很长的公式,但效率很高,可用于其他功能。尝试使用较短的公式会导致性能显着下降,并且由于某种原因,阵列无法用于其他功能。

该解决方案结合了5个不同的素数生成器,以增加生成的随机数的变化。引入了一些任意常数以试图减少重复模式。

这具有正确的分布和相当好的随机性。使用10,000的SampleSize重复测试导致个体数字的频率在960和1040之间变化,没有总体偏袒。然而它似乎有一个奇怪的属性,从来没有连续两次生成相同的数字!

答案 2 :(得分:-1)

这不是一个好的答案,但考虑到易失性函数的限制,使用具有易失性函数的IF公式和工作表中某处放置的易失性变量绝对是一个可能的答案。

我使用以下公式来获得所需的结果

{{1}}

我将单元格B12设置为rngIsVolatile。我粘贴了下面的截图,看看它是否有效。

IF Formula to limit volatility of Volatile Functions

当rngIsVolatile设置为True时,它会从randArray中获取新值: Volatile Function Result #01

当rngIsVolatile设置为False时,它会从A1中获取旧值:A10: Volatile Function Result #02