【问题标题】:How can I determine the statistical randomness of a binary string?如何确定二进制字符串的统计随机性?
【发布时间】:2011-03-07 02:12:28
【问题描述】:

如何确定二进制字符串的统计随机性?

Ergo,我如何编写自己的测试代码,并返回一个与统计随机性相对应的单个值,一个介于 0 和 1.0 之间的值(0 表示非随机,1.0 表示随机)?

测试需要处理任何大小的二进制字符串。

当您使用笔和纸进行操作时,您可能会像这样探索字符串:
0(任意随机,唯一的选择是1)
00(不是随机的,它是重复的并且与大小匹配)
01(更好,两个不同的值)
010(较少随机,回文)
011(更少随机,更多 1,仍然可以接受)
0101(少随机,花样)
0100(更好,更少,但任何其他分布都会导致模式)

案例:

尺寸:1,可能性:2
0:1.0(随机)
1:1.0(随机)

尺寸:2,P:4
00: ?
01:1.0(随机)
10:1.0(随机)
11:?

S:3, P:8
000:?非随机
001:1.0(随机)
010:?不那么随机
011:1.0(随机)
100:1.0(随机)
101:?不那么随机
110 1.0(随机)
111:?非随机

等等。

我觉得这对于将字符串分解为所有可能的子字符串并比较频率可能起到了很大的作用,但似乎这种基础工作在计算机科学的早期就应该已经完成​​了。

【问题讨论】:

  • 任何单个二进制字符串都可以被视为随机的!你需要有一个样本空间来比较它...
  • 你到底想做什么?
  • 就是这样:读取任意二进制字符串,并注意其统计随机性。例如,0101010101010101 具有平衡的 1 和 0 数量,但几乎不是随机的。可以这样说:[00000000 的随机性为 0] [01010101 的随机性为 0.01] [00000101 的随机性为 0.05] [01001011 的随机性为 1.0]
  • 您提出的问题比您预期的要难。您是否有任何特定的随机性测试要实施?统计随机性的维基百科页面列出了一些更简单的测试。您可能不得不去期刊文章寻找更有趣的文章。你用这个测试做什么?这可能会影响哪些测试是相关的。你真正想测量什么?也许:观察到的字符串是从真正的随机生成器生成的概率?
  • 哈!你的案例是一部非常好的喜剧。在随机字节串中,它们中的任何一个都会像另一个一样频繁出现!

标签: c++ algorithm entropy random


【解决方案1】:

您似乎在寻找一种方法来查找二进制字符串的 Kolmogorov 复杂度。可悲的是,这是incomputable。通过压缩算法运行字符串后的大小将使您了解它的随机性,因为随机字符串越多,压缩性越小。

【讨论】:

  • 确实如此。将“随机度”定义为“压缩文件与未压缩文件的比率”。这是您可能得到的最接近的结果。
  • 这似乎(几乎)正是您正在寻找的。选择一种压缩算法,但不幸的是没有一个是完美的。我不确定我是否知道任何压缩回文的压缩算法,但我所知道的几乎所有算法都可以压缩重复序列。
【解决方案2】:

这将为您提供从 0 到 1.0 的熵计数:

您可能想尝试查看Shannon Entropy,这是一种应用于数据和信息的熵度量。事实上,它实际上几乎是热力学最公认的解释所定义的熵的物理公式的直接模拟。

更具体地说,在您的情况下,使用二进制字符串,您可以看到 Binary Entropy Function,这是一种涉及二进制数据位随机性的特殊情况。

这是由

计算的
H(p) = -p*log(p) - (1-p)*log(1-p)

(以 2 为底的对数;假设 0*log(0) 为 0)

p 是您占 1 的百分比(或占 0 的百分比;图形是对称的,因此无论哪种方式,您的答案都是相同的)

这是函数产生的结果:

如您所见,如果 p 为 0.5(1 的数量与 0 的数量相同),则您的熵最大 (1.0)。如果p 为 0 或 1.0,则熵为 0。

这似乎正是你想要的,对吧?

唯一的例外是您的 Size 1 箱子,可以将其视为例外。但是,100% 0 和 100% 1 对我来说似乎并不太熵。但随心所欲地实施它们。

此外,这不考虑位的任何“排序”。只有它们的总和。所以,重复/回文不会得到任何提升。您可能需要为此添加额外的启发式方法。

以下是您的其他案例:

00:-0*log(0) - (1-0)*log(1-0) = 0.0 01:-0.5*log(0.5) - (1-0.5)*log(1-0.5) = 1.0 010:-(1/3)*log(1/3)-(2/3)*log(2/3) = 0.92 0100:-0.25*log(0.25) - (1-0.25)*log(1-0.25) = 0.81

【讨论】:

    【解决方案3】:

    前段时间,我开发了一种简单的启发式方法,适用于我的目的。

    您不仅可以计算字符串本身的 0 和 1 的“偶数”,还可以计算字符串的导数。例如,01010101 的一阶导数是 11111111,因为每一位都在变化,二阶导数是 00000000,因为一阶导数中没有位变化。然后,您只需根据自己的口味权衡这些“均匀度”。

    这是一个例子:

    #include <string>
    #include <algorithm>
    
    float variance(const std::string& x)
    {
        int zeroes = std::count(x.begin(), x.end(), '0');
        float total = x.length();
        float deviation = zeroes / total - 0.5f;
        return deviation * deviation;
    }
    
    void derive(std::string& x)
    {
        char last = *x.rbegin();
        for (std::string::iterator it = x.begin(); it != x.end(); ++it)
        {
            char current = *it;
            *it = '0' + (current != last);
            last = current;
        }
    }
    
    float randomness(std::string x)
    {
        float sum = variance(x);
        float weight = 1.0f;
        for (int i = 1; i < 5; ++i)
        {
            derive(x);
            weight *= 2.0f;
            sum += variance(x) * weight;
        }
        return 1.0f / sum;
    }
    
    int main()
    {
        std::cout << randomness("00000000") << std::endl;
        std::cout << randomness("01010101") << std::endl;
        std::cout << randomness("00000101") << std::endl;
    }
    

    您的示例输入产生的“随机性”分别为 0.129032、0.133333 和 3.2。

    顺便说一句,您可以通过导出字符串来获得很酷的分形图形;)

    int main()
    {
        std::string x = "0000000000000001";
        for (int i = 0; i < 16; ++i)
        {
            std::cout << x << std::endl;
            derive(x);
        }
    }
    
    0000000000000001
    1000000000000001
    0100000000000001
    1110000000000001
    0001000000000001
    1001100000000001
    0101010000000001
    1111111000000001
    0000000100000001
    1000000110000001
    0100000101000001
    1110000111100001
    0001000100010001
    1001100110011001
    0101010101010101
    1111111111111111
    

    【讨论】:

    • 我不认为这是对 Komologorov 复杂性的理论上合理的处理,但您可能有兴趣注意到这实际上是规则 60 基本元胞自动机:mathworld.wolfram.com/Rule60.html
    【解决方案4】:

    您可以尝试对字符串进行压缩算法。重复越多(随机性越小),字符串可以压缩的越多。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-22
      • 2012-11-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多