Math 如何测试随机性(以点洗牌为例)
首先,这个问题是从问题中删去的。我这样做是因为我认为这部分比一个较长问题的一个子部分要大。如果冒犯了你,请原谅我 假设您有一个生成随机性的算法。现在如何测试它? 或者更直接一点,假设你有一个洗牌算法,你如何测试它是一个完全随机的算法 给这个问题添加一些理论- 一副牌可以在52秒内洗牌!(52阶乘)不同的方式。拿一副牌,用手洗牌,写下所有牌的顺序。你得到洗牌的可能性有多大?答复:1/52 洗牌后,你得到A,K,Q,J。。。一系列的每一套衣服?回答1/52 因此,只需随机移动一次并查看结果,就绝对不会得到有关随机移动算法的任何信息。两次你会得到更多的信息,三次甚至更多Math 如何测试随机性(以点洗牌为例),math,theory,random,puzzle,Math,Theory,Random,Puzzle,首先,这个问题是从问题中删去的。我这样做是因为我认为这部分比一个较长问题的一个子部分要大。如果冒犯了你,请原谅我 假设您有一个生成随机性的算法。现在如何测试它? 或者更直接一点,假设你有一个洗牌算法,你如何测试它是一个完全随机的算法 给这个问题添加一些理论- 一副牌可以在52秒内洗牌!(52阶乘)不同的方式。拿一副牌,用手洗牌,写下所有牌的顺序。你得到洗牌的可能性有多大?答复:1/52 洗牌后,你得到A,K,Q,J。。。一系列的每一套衣服?回答1/52 因此,只需随机移动一次并查看结果,就绝对不
你如何用黑盒测试随机性的洗牌算法?洗牌很多,然后记录结果(如果我读对了的话)。我记得看到过“随机数生成器”的比较。他们只是一次又一次地测试,然后将结果绘制成图表
如果真的是随机的,那么图形大部分是均匀的。测试随机性的唯一方法是编写一个程序,尝试为被测数据建立一个预测模型,然后使用该模型尝试预测未来数据,然后显示其预测的不确定性或熵趋于最大(即均匀分布)随着时间的推移。当然,你总是不确定你的模型是否捕捉到了所有必要的背景;给定一个模型,你总是有可能构建第二个模型,生成第一个看起来随机的非随机数据。但只要你接受冥王星轨道对实验结果的影响微不足道洗牌算法,然后你应该能够满足自己的结果是可以接受的随机性
当然,如果您这样做,您也可以生成性地使用您的模型来实际创建您想要的数据。如果您这样做,那么您就回到了原点。统计数据。测试RNG的事实标准是。或者,提供的测试更易于解释,但不太全面 至于洗牌算法,请使用一种众所周知的算法,如(又称“Knuth Shuffle”)。只要底层RNG是一致随机的,洗牌将是一致随机的。如果您使用Java,则此算法可在标准库中找到(请参阅)
对于大多数应用程序来说,这可能并不重要,但请注意,大多数RNG并没有提供足够的自由度来生成52卡组的所有可能排列(已解释)。我没有完全理解你的问题。你说 假设您有一个生成随机性的算法。现在如何测试它 你是什么意思?如果你假设你能产生随机性,就没有必要测试它 一旦你有了一个好的随机数生成器,创建一个随机排列就很容易了(例如,将你的卡片称为1-52。生成52个随机数,将每个随机数按顺序分配给一张卡片,然后根据52个随机数进行排序)。你不会通过生成排列来破坏你的好RNG的随机性
困难的问题是你是否能信任你的RNG。一个指向在特定环境中讨论该问题的人的示例链接。首先,不可能确定某个有限输出是否“真正随机”,因为正如你所指出的那样 可以做的是,获取一个输出序列,并对照更可能的结果检查该序列的各种测量值。您可以得出一种置信度评分,表明生成算法做得很好 例如,您可以检查10次不同洗牌的输出。为每张牌指定一个数字0-51,并在洗牌过程中取位于第6位的牌的平均值。收敛平均值为25.5,因此您会惊讶地看到这里的值为1。您可以使用中心极限定理来估计每个平均值为f的可能性或者一个给定的位置 但是我们不应该停在这里!因为这个算法可能会被一个只在两次洗牌之间交替的系统所愚弄,而这两次洗牌的目的是在每个位置给出25.5的精确平均值。我们如何才能做得更好 我们期望均匀分布(任何给定卡的可能性相等)在每个位置,跨越不同的洗牌。因此,在10次洗牌中,我们可以尝试验证选择“看起来一致”。这基本上只是原始问题的简化版本。您可以检查标准偏差是否合理,最小值是否合理,以及最大值。您还可以检查其他vaLUE,例如最近的两张牌(根据我们分配的号码),也有意义
但我们也不能无限期地添加各种度量值,因为,如果有足够的统计数据,任何特定的洗牌都不太可能出于某种原因出现(例如,这是极少数牌X、Y、Z按顺序出现的洗牌之一)因此,最大的问题是:哪一套测量方法是正确的?在这里我不得不承认我不知道最好的答案。但是,如果你有一个特定的应用程序,你可以选择一套好的属性/测量方法进行测试,并使用它们——这似乎是密码学家处理事情的方式。有很多方法是错误的关于随机性测试的理论。对于一个非常简单的卡片洗牌算法测试,你可以进行大量洗牌,然后进行卡方检验,确定每张卡片出现在任何位置的概率是一致的。但这不能测试连续的汽车
// ...
int main() {
typedef std::map<std::pair<size_t, Deck::value_type>, size_t> Map;
Map freqs;
Deck d;
const size_t ntests = 100000;
// compute frequencies of events: card at position
for (size_t i = 0; i < ntests; ++i) {
d.shuffle();
size_t pos = 0;
for(Deck::const_iterator j = d.begin(); j != d.end(); ++j, ++pos)
++freqs[std::make_pair(pos, *j)];
}
// if Deck.shuffle() is correct then all frequencies must be similar
for (Map::const_iterator j = freqs.begin(); j != freqs.end(); ++j)
std::cout << "pos=" << j->first.first << " card=" << j->first.second
<< " freq=" << j->second << std::endl;
}
/**
* This is a rudimentary check to ensure that the output of a given RNG
* is approximately uniformly distributed. If the RNG output is not
* uniformly distributed, this method will return a poor estimate for the
* value of pi.
* @param rng The RNG to test.
* @param iterations The number of random points to generate for use in the
* calculation. This value needs to be sufficiently large in order to
* produce a reasonably accurate result (assuming the RNG is uniform).
* Less than 10,000 is not particularly useful. 100,000 should be sufficient.
* @return An approximation of pi generated using the provided RNG.
*/
public static double calculateMonteCarloValueForPi(Random rng,
int iterations)
{
// Assumes a quadrant of a circle of radius 1, bounded by a box with
// sides of length 1. The area of the square is therefore 1 square unit
// and the area of the quadrant is (pi * r^2) / 4.
int totalInsideQuadrant = 0;
// Generate the specified number of random points and count how many fall
// within the quadrant and how many do not. We expect the number of points
// in the quadrant (expressed as a fraction of the total number of points)
// to be pi/4. Therefore pi = 4 * ratio.
for (int i = 0; i < iterations; i++)
{
double x = rng.nextDouble();
double y = rng.nextDouble();
if (isInQuadrant(x, y))
{
++totalInsideQuadrant;
}
}
// From these figures we can deduce an approximate value for Pi.
return 4 * ((double) totalInsideQuadrant / iterations);
}
/**
* Uses Pythagoras' theorem to determine whether the specified coordinates
* fall within the area of the quadrant of a circle of radius 1 that is
* centered on the origin.
* @param x The x-coordinate of the point (must be between 0 and 1).
* @param y The y-coordinate of the point (must be between 0 and 1).
* @return True if the point is within the quadrant, false otherwise.
*/
private static boolean isInQuadrant(double x, double y)
{
double distance = Math.sqrt((x * x) + (y * y));
return distance <= 1;
}
// A card has a Number 0-51 and a position 0-51
int[][] StatMatrix = new int[52][52]; // Assume all are set to 0 as starting values
ShuffleCards();
ForEach (card in Cards) {
StatMatrix[Card.Position][Card.Number]++;
}
statMatrix[position][card] / numberOfShuffle = 1/52.