为什么这段 C 代码输出的数据会形成有趣的波浪状直方图?

Why does this C code output a data which makes an interesting wave-like histogram?

假设我使用 here 中的 dictionary.txt(单词词典),并且此 C 代码生成如下数据:

#include <stdio.h>

int main ( void )
{
   FILE *dictionary = fopen ( "dictionary.txt", "r" );

   char entry[46];
   unsigned value = 0;

   while ( fscanf ( dictionary, "%s", entry ) != EOF ) {
      for ( int i = 0; entry[i]; ++i )
         value += entry[i];
      printf ( "%d"\n", value );
      value = 0;
   }

   fclose ( dictionary );

   return 0;
}

这段代码的作用是,它为字典中的每个单词生成一个值,该值是每个字母的所有 ASCII 值的总和。

编译后,我做了一个 data.txt 来收集终端上的所有值:

$ ./dictionary > data.txt

在 MATLAB 上:

fileID = fopen ( 'data.txt', 'r' );
formatSpec = '%u';
A = fscanf ( fileID, formatSpec );
fclose(fileID);

X = min(A):max(A);
hist ( A, X )

输出的直方图如下所示:

您正在绘制的是文本文件中以白色-space 分隔的字符串的累加 ASCII 值的直方图。按照名字我猜是英文词典

英文以小写字母为主,ASCII码从97(a)到122(z),平均110个(忽略字母频率)。直方图显示距离也约为 110 的峰值。因此,不同的峰值对应于不同长度的单词。可辨别的峰值似乎对应于字长 从 1 到大约 21 个字母 更新: 4 到 12 个字母,最常见的字长是 8 个字母.

单峰的形状大致呈正态分布,这可以用"randomly"从大约'a'到[=41的范围内选择不同的字母来解释=].虽然这些选择肯定不是独立同分布的,但似乎仍然会发生中心极限定理所描述的效果。


问题编辑后更新:文件确实是一个英文单词列表,每行一个,全部用小写字母书写。进一步分析:

所有单词的字母合在一起的ASCII值在词典中的绝对频率如下:
所有出现的值都在 97 (a) 和 122 (z) 之间。均值为107.5,标准差为6.89.

词典中单词长度出现的频率是:
我上面的解释最常见的字长是8,结果是正确的,但字长的范围实际上是4到12。问题中更新的直方图与此一致。

现在,如果我们通过从所有字母池中随机抽取来模拟 4 个、8 个和 12 个字母的单词,然后绘制 ASCII 和直方图,结果如下:
它表明,不同长度的词不仅导致峰值具有不同的均值(此处:430、860 和 1290),而且还具有不同的宽度(此处:标准差 13.78、19.49 和 23.91)以及相应的不同高度。

因此,您在直方图中看到的图片是字长直方图和不同字长的 ASCII 值之和的组合。

假设字典全部小写。

1 个字母的单词总和在 97-122 范围内。

2 个字母的单词的总和在 194-244 范围内。

3 个字母的单词的总和在 291-366 范围内。

4 个字母的单词的总和在 388-488 范围内。

5 个字母的单词的总和在 485-610 范围内。

直到现在,范围才开始重叠,即便如此,也只有 zzzzaaaaa 这样的词。中间值较少或不存在,除非单词以大写字母开头或可能包含连字符。所以如前所述,频率峰值将是大约 110 的倍数。

14个字母单词的和在1358-1708范围内

15个字母的单词和在1455-1830范围内

如果每个词长的直方图都具有自然分布,你可以通过组合直方图看到这一点。