8

好的,我一直在研究随机图像选择器和队列系统(所以你不会经常看到相同的图像)。

一切都在顺利进行(就我糟糕的代码而言),直到我到达随机位。我想测试它,但你如何测试它?没有Debug.Assert(i.IsRandom)(可悲):D

所以,我在用茶给它浇水后开始思考它并想出了以下内容,我只是想知道我是否可以有你的想法?

  • 基本上我知道随机位是问题所在,所以我把它撕掉给一个委托(然后将它传递给对象构造函数)。
  • 然后我创建了一个类,它执行的逻辑几乎与实时代码相同,但会记住在私有变量中选择的值。
  • 然后我把那个代表扔到了现场课堂上并对此进行了测试:

IE

Debug.Assert(myObj.RndVal == RndIntTester.ValuePassed);

但我忍不住想,我是在浪费时间吗?我通过大量的迭代运行它,看看它是否会在任何时候倒下等。

你认为我在这件事上浪费时间吗?或者我可以逃脱:

真棒随机数生成器

GateKiller 的回答让我想起了这一点:

呆伯特随机

更新澄清

  • 我应该补充一点,我基本上不想从 Y 大小的池中看到相同的结果超过 X 次。
  • 测试容器的添加基本上让我可以查看之前选择的任何图像是否是“随机”选择的。
  • 从技术上讲,我猜这里正在测试的东西不是 RNG(因为我从未编写过该代码),而是我期望来自有限池的随机结果,并且我想跟踪它们。
4

19 回答 19

6

从要求测试:“所以你不会经常看到相同的图像”

要求 100 张图片。您是否经常看到图像?

于 2008-09-23T18:49:18.397 回答
6

维基百科上有一个统计随机性测试和相关研究的方便列表。请注意,您无法确定其中大多数来源是真正随机的,您只是排除了一些可能很容易预测的方式。

于 2008-09-23T19:01:44.263 回答
5

如果您有一组固定的项目,并且您不希望它们过于频繁地重复,请随机打乱集合。然后您将确保您不会连续两次看到相同的图像,感觉就像您正在收听 Top 20 广播等。您将在重复之前完整浏览该集合。

Item[] foo = …
for (int idx = foo.size(); idx > 1; --idx) {
  /* Pick random number from half-open interval [0, idx) */
  int rnd = random(idx); 
  Item tmp = foo[idx - 1];
  foo[idx - 1] = foo[rnd];
  foo[rnd] = tmp;
}

如果您有太多的项目需要一次收集和洗牌(存储库中有成千上万的图像),您可以在相同的方法中添加一些分而治之的方法。洗牌图像组,然后洗牌每组。

听起来可能适用于您修改后的问题陈述的稍微不同的方法是让您的“图像选择器”实现将其最近的选择历史保留在最多Y长度的队列中。在返回一张图片之前,它会测试它是否X已经在队列中,如果是,它会随机选择另一个,直到找到一个通过。

如果您真的要问测试随机数生成器的质量,我将不得不打开统计书。

于 2008-09-23T18:31:46.333 回答
4

不可能测试一个值是否真的是随机的。您能做的最好的事情就是多次执行测试并测试您是否获得了适当的分布,但如果结果确实是随机的,那么即使这也有(非常小)失败的机会。

如果您正在进行白盒测试,并且您知道随机种子,那么您实际上可以计算预期结果,但您可能需要单独的测试来测试 RNG 的随机性。

于 2008-09-23T18:20:43.113 回答
2

随机数的生成太重要了,不能靠运气。——罗伯特·R·科维尤

解决心理问题:

防止明显重复的一个不错的方法是从全套中随机选择一些项目,丢弃重复项。播放这些,然后选择另外几个。“几”是多少取决于你玩它们的速度和整套的大小,但例如避免在“20”中的较大者内重复,“5 分钟”可能没问题。做用户测试——作为程序员,你会厌倦幻灯片,你不是一个好的测试对象。

要测试随机化代码,我会说:

第 1 步:指定代码必须如何将原始随机数映射到您的域中的选择,并确保您的代码正确使用随机数生成器的输出。通过模拟生成器来测试它(或者如果它是 PRNG,则使用已知的测试值播种它)。

第 2 步:确保生成器对于您的目的足够随机。如果你使用了库函数,你可以通过阅读文档来做到这一点。如果你自己写,为什么?

第 3 步(仅限高级统计学家):对生成器的输出运行一些随机性统计测试。确保您知道测试中错误失败的概率是多少。

于 2008-09-23T18:38:16.817 回答
2

有一整本书可以写关于随机性和评估某些东西是否看起来是随机的,但我会为你保存数学页面。简而言之,您可以使用卡方检验来确定明显的“随机”分布与您的期望的匹配程度。

如果您使用 Perl,您可以使用Statistics::ChiSquare模块为您完成繁重的工作。

但是,如果您想确保图像分布均匀那么您可能不希望它们真正随机。相反,我建议您获取整个图像列表,对该列表进行洗牌,然后在需要“随机”图像时从中删除一个项目。当列表为空时,您重新构建它,重新洗牌并重复。

这种技术意味着给定一组图像,每个单独的图像在您的列表中每次迭代都不能出现多次。您的图像不能不均匀分布。

祝一切顺利,

保罗

于 2008-09-24T06:59:14.913 回答
1

Random和类似函数给您的只是伪随机数,即通过函数产生的一系列数字。通常,您给该函数提供第一个输入参数(也称为“种子”),用于产生第一个“随机”数字。之后,每个最后一个值都用作循环下一次迭代的输入参数。您可以查看有关“伪随机数生成器”的维基百科文章,那里的解释非常好。

所有这些算法都有一个共同点:该系列在多次迭代后会重复自身。请记住,这些并不是真正的随机数,只是看似随机的一系列数字。要选择一个发电机而不是另一个,你需要问自己:你想要它做什么?

你如何测试随机性?确实可以。有很多测试。当然,第一个也是最简单的方法是大量运行伪随机数生成器,并编译每个结果出现的次数。最后,每个结果应该出现多次非常接近(迭代次数)/(可能结果的数量)。这个标准偏差越大,你的发电机越差。

第二个是:你当时使用了多少随机数?2、3? 将它们成对(或三胞胎)并重复之前的实验:经过非常长的迭代次数后,每个预期结果应该至少出现一次,并且每个结果出现的次数应该不会太远预期的。有一些生成器一次可以使用一个或 2 个,但是当您使用 3 个或更多时会发生惊人的故障(RANDU 有人吗?)。

还有其他更复杂的测试:有些涉及以对数刻度绘制结果,或者在中间有一个圆圈的平面上,然后计算有多少图落在其中,其他......我相信上面的 2 应该足够了大多数时候(除非你是一个挑剔的数学家)。

于 2008-09-23T19:09:47.023 回答
0

随机就是随机。即使同一张图片连续出现 4 次,它仍然可以被认为是随机的。

于 2008-09-23T18:19:36.737 回答
0

我的观点是,任何随机的东西都无法正确测试。

当然你可以尝试测试它,但是有很多组合可以尝试,你最好只依靠 RNG 并抽查大量案例。

于 2008-09-23T18:22:13.533 回答
0

好吧,问题在于定义上的随机数可以重复(因为它们是......等待它:随机)。也许您想要做的是保存最新的随机数并将计算出的随机数与该随机数进行比较,如果相等,则计算另一个...但是现在您的数字不那么随机了(我知道没有“或多或少”之类的东西随机性,但这次让我使用这个词),因为它们保证不会重复。

无论如何,你永远不应该过多考虑随机数。:)

于 2008-09-23T18:25:46.770 回答
0

正如其他人指出的那样,不可能真正测试随机性。您可以(并且应该)将随机性包含在一个特定方法中,然后为其他所有方法编写单元测试。这样,您可以测试所有其他功能,假设您可以从最后一部分中获得一个随机数。

于 2008-09-23T18:27:37.623 回答
0

存储随机值,在使用下一个生成的随机数之前,检查存储的值。

于 2008-09-23T18:35:16.543 回答
0

任何好的伪随机数生成器都可以让你播种生成器。如果您使用相同的数字作为生成器的种子,则生成的随机数流将是相同的。那么为什么不播种随机数生成器,然后根据特定的数字流创建单元测试呢?

于 2008-09-23T18:40:43.067 回答
0

要获得一系列不重复的随机数:

  1. 创建一个随机数列表。
  2. 为每个随机数添加一个序列号
  3. 按原始随机数对有序列表进行排序
  4. 使用您的序列号作为新的随机数。
于 2008-09-23T19:06:34.610 回答
0

不要测试随机性,测试你得到的结果是否合意(或者,在接受你的结果可能是合意的之前,尝试获得不合意的结果几次)。如果您正在测试随机输出,将不可能确保您永远不会得到不想要的结果,但您至少可以增加您注意到它发生的机会。

我要么取 N 个 Y 大小的池,检查出现超过 X 次的任何结果,要么取一个 N*Y 大小的池,检查每组 Y 大小的任何结果出现超过 X 次(1到 Y、2 到 Y + 1、3 到 Y + 2 等)。N 是多少取决于您希望测试的可靠性。

于 2008-09-23T19:09:07.663 回答
0

随机数是从分布中生成的。在这种情况下,每个值都应该具有相同的出现概率。如果你计算无限数量的随机数,你会得到精确的分布。

在实践中,多次调用该函数并检查结果。如果您希望有 N 个图像,请计算 100*N 个随机数,然后计算找到每个预期数字的数量。大多数应该出现70-130次。用不同的随机种子重新运行测试,看看结果是否不同。

如果您发现您现在使用的生成器不够好,您可以轻松找到一些东西。谷歌搜索“Mersenne Twister”——这比你需要的要随机得多。

为避免图像重新出现,您需要一些不那么随机的东西。一种简单的方法是检查不允许的值,如果是其中之一,则重新计算。

于 2008-09-23T19:25:16.110 回答
0

虽然您无法测试随机性,但您可以测试数字序列的相关性或分布。

难以测试的目标:每次我们需要一张图片时,随机选择 4 张图片中的 1 张。

易于测试的目标:对于我们选择的每 100 张图片,4 张图片中的每张都必须至少出现 20 次。

于 2008-09-23T19:31:52.587 回答
0

我同意亚当·罗森菲尔德的观点。对于您正在谈论的情况,您唯一可以有效测试的是整个范围内的分布。

我经常遇到的情况是我用我最喜欢的语言的 PRNG 生成伪随机数,然后将它们操纵到所需的范围内。为了检查我的操作是否影响了分布,我生成了一堆数字,对其进行操作,然后检查结果的分布。

要获得良好的测试,您应该生成至少比您的范围多几个数量级的数字。您使用的值越多,测试就越好。显然,如果你有一个非常大的范围,这是行不通的,因为你必须生成太多的数字。但是在您的情况下,它应该可以正常工作。

这是 Perl 中的一个示例,说明了我的意思:

for (my $i=0; $i<=100000; $i++) {
   my $r = rand;        # Get the random number
   $r = int($r * 1000); # Move it into the desired range
   $dist{$r} ++;        # Count the occurrences of each number
}

print "Min occurrences: ", (sort { $a <=> $b } values %dist)[1], "\n";
print "Max occurrences: ", (sort { $b <=> $a } values %dist)[1], "\n";

如果最小和最大出现之间的差异很小,那么您的分布是好的。如果它很宽,那么您的分布可能很糟糕。您还可以使用这种方法来检查您的范围是否被覆盖以及是否遗漏了任何值。

同样,您生成的数字越多,结果就越有效。我倾向于从小处着手,然后在合理的时间内(例如五分钟)完成我的机器所能处理的任何事情。

于 2008-09-23T19:57:43.240 回答
0

假设您正在测试整数范围内的随机性,验证这一点的一种方法是创建一个数以百万计(嗯,可能是 10,000 左右)的“随机”数,并将它们的出现绘制在直方图上。

          ******    ******           ****
***********************************************
*************************************************
*************************************************
*************************************************
*************************************************
*************************************************
*************************************************
*************************************************
*************************************************
         1         2         3         4         5
12345678901234567890123456789012345678901234567890

上面显示了一个“相对”的正态分布。

如果它看起来更偏斜,例如:

          ******    ******           ****
    ************  ************  ************
    ************  ************  ***************
    ************  ************  ****************
    ************  ************  *****************
    ************  ************  *****************
   ***************************  ******************
   **************************** ******************
******************************* ******************
**************************************************
         1         2         3         4         5
12345678901234567890123456789012345678901234567890

然后你可以看到随机性减少了。正如其他人所提到的,还有重复的问题需要解决。

如果您要使用生成器编写一个包含 10,000 个随机数的二进制文件,例如从 1 到 1024 的随机数,并尝试使用某种压缩(zip、gzip 等)压缩该文件,那么您可以比较这两个文件尺寸。如果有“大量”压缩,那么它就不是特别随机的。如果大小没有太大变化,那么它是“非常随机的”。

为什么这有效

压缩算法寻找模式(重复和其他)并以某种方式减少它。查看这些压缩算法的一种方法是衡量文件中的信息量。高度压缩的文件信息少(例如随机性),压缩程度低的文件信息多(随机性)

于 2008-09-23T20:57:05.627 回答