11

如何根据常用语音中的使用频率随机生成字母?

任何伪代码都值得赞赏,但 Java 中的实现会很棒。否则,只需朝正确的方向戳一下就会有帮助。

注意:我不需要生成使用频率——我确信我可以很容易地找到它。

4

5 回答 5

19

我假设您将频率存储为 0 到 1 之间的浮点数,总计为 1。

首先,您应该准备一个累积频率表,即该字母和之前所有字母的频率之和。

为简化起见,如果您从这个频率分布开始:

A  0.1
B  0.3
C  0.4
D  0.2

您的累积频率表将是:

A  0.1
B  0.4 (= 0.1 + 0.3)
C  0.8 (= 0.1 + 0.3 + 0.4)
D  1.0 (= 0.1 + 0.3 + 0.4 + 0.2)

现在生成一个介于 0 和 1 之间的随机数,并查看该数字在此列表中的位置。选择最小累积频率大于随机数的字母。一些例子:

假设您随机选择 0.612。这介于 0.4 和 0.8 之间,即 B 和 C 之间,所以你会选择 C。

如果你的随机数是 0.039,它在 0.1 之前,即在 A 之前,所以选择 A。

我希望这是有道理的,否则请随时要求澄清!

于 2010-01-27T20:20:10.107 回答
11

一种快速的方法是生成一个字母列表,其中每个字母根据其频率出现在列表中。比如说,如果“e”的使用率为 25.6%,并且您的列表长度为 1000,那么它将有 256 个“e”。

然后,您可以通过使用(int) (Math.random() * 1000)生成 0 到 999 之间的随机数从列表中随机选择点。

于 2010-01-27T20:14:35.783 回答
5

我要做的是将相对频率缩放为浮点数,使它们的总和为 1.0。然后,我将创建一个包含每个字母的累积总数的数组,即为获得该字母以及所有“低于”它的字母必须加满的数字。假设 A 的频率为 10%,b 为 2%,z 为 1%;那么您的表格将如下所示:

0.000 A ; from 0% to 10% gets you an A
0.100 B ; above 10% is at least a B
0.120 C ; 12% for C...
...
0.990 Z ; if your number is >= 99% then you get a Z

然后你自己生成一个介于 0.0 和 1.0 之间的随机数,并在数组中对小于随机数的第一个数字进行二进制搜索。然后选择那个位置的字母。完毕。

于 2010-01-27T20:23:27.120 回答
4

甚至不是伪代码,而是一种可能的方法如下:

让 p1, p2, ..., pk 成为您想要匹配的频率。

  1. 计算累积频率:p1, p1+p2, p1+p2+p3, ... , 1
  2. 生成一个随机均匀 (0,1) 数 x
  3. 检查累积频率 x 属于哪个区间:如果它在 p1+..+pi 和 p1+...+pi+p(i+1) 之间,则输出第 (i+1) 个字母

根据您实现区间查找的方式,如果 p1,p2,... 按降序排序,该过程通常会更有效,因为您通常会更快地找到包含 x 的区间。

于 2010-01-27T20:20:14.820 回答
2

使用二叉树为您提供了一种很好、干净的方式来找到正确的条目。在这里,您从一张frequency地图开始,其中键是符号(英文字母),值是它们出现的频率。这会被反转,并NavigableMap创建 a ,其中键是累积概率,值是符号。这使查找变得容易。

  private final Random generator = new Random();

  private final NavigableMap<Float, Integer> table = 
    new TreeMap<Float, Integer>();

  private final float max;

  public Frequency(Map<Integer, Float> frequency)
  {
    float total = 0;
    for (Map.Entry<Integer, Float> e : frequency.entrySet()) {
      total += e.getValue();
      table.put(total, e.getKey());
    }
    max = total;
  }

  /** 
   * Choose a random symbol. The choices are weighted by frequency.
   */ 
  public int roll()
  {
    Float key = generator.nextFloat() * max;
    return table.higherEntry(key).getValue();
  }
于 2010-01-27T21:10:54.557 回答