Math 如何测试随机性(以点洗牌为例)

Math 如何测试随机性(以点洗牌为例),math,theory,random,puzzle,Math,Theory,Random,Puzzle,首先,这个问题是从问题中删去的。我这样做是因为我认为这部分比一个较长问题的一个子部分要大。如果冒犯了你,请原谅我 假设您有一个生成随机性的算法。现在如何测试它? 或者更直接一点,假设你有一个洗牌算法,你如何测试它是一个完全随机的算法 给这个问题添加一些理论- 一副牌可以在52秒内洗牌!(52阶乘)不同的方式。拿一副牌,用手洗牌,写下所有牌的顺序。你得到洗牌的可能性有多大?答复:1/52 洗牌后,你得到A,K,Q,J。。。一系列的每一套衣服?回答1/52 因此,只需随机移动一次并查看结果,就绝对不

首先,这个问题是从问题中删去的。我这样做是因为我认为这部分比一个较长问题的一个子部分要大。如果冒犯了你,请原谅我

假设您有一个生成随机性的算法。现在如何测试它? 或者更直接一点,假设你有一个洗牌算法,你如何测试它是一个完全随机的算法

给这个问题添加一些理论- 一副牌可以在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.