Генерация букв с заданными частотами в C#

В этом примере генерируются случайные буквы с частотами, которые они имеют в обычном английском тексте. Следующий код показывает, как этот пример запускается.
// Частоты букв. Видеть:
// http://en.wikipedia.org/wiki/Letter_frequency
private float[] Frequencies =
{
8.167f, 1.492f, 2.782f, 4.253f, 12.702f,
2.228f, 2.015f, 6.094f, 6.966f, 0.153f,
0.772f, 4.025f, 2.406f, 6.749f, 7.507f,
1.929f, 0.095f, 5.987f, 6.327f, 9.056f,
2.758f, 0.978f, 2.360f, 0.150f, 1.974f,
0.074f
};
// Генератор случайных чисел.
private Random Rand = new Random();
// Значение ASCII A.
private int int_A = (int)'A';
// Удостоверьтесь, что частоты составляют до 100.
private void Form1_Load(object sender, EventArgs e)
{
// Дайте разницу E.
float total = Frequencies.Sum();
float diff = 100f - total;
Frequencies[(int)'E' - int_A] += diff;
}
В массиве Frequencies содержатся относительные процентные частоты букв, перечисленные в . Этот пример рассматривает эти числа как проценты, так что, например, буква A должна появиться примерно в 8,176% времени. Если эти числа являются некоторыми другими значениями, такими как фракции между 0 и 1, вы можете соответствующим образом настроить программу. Если они подсчитываются, например, количество вхождений в определенном фрагменте текста, вы можете добавить их для преобразования их в проценты.
Код создает объект Random и определяет значение буквы A как целое для дальнейшего удобства.
Обработчик событий Load в форме добавляет все значения в Frequencies. В этом примере частоты не составляют до 100%, потому что они не на странице Википедии, где я их получил. Чтобы сделать общее количество до 100%, код добавляет их, вычитает общее количество из 100 и добавляет разницу в букву E, увеличивая или уменьшая частоту E немного, так что общее количество составляет 100%.
При нажатии кнопки «Создать» выполняется следующий код.
// Генерируем случайные буквы с указанными частотами.
private void btnGenerate_Click(object sender, EventArgs e)
{
// Следите за количеством каждой сгенерированной буквы.
int[] counts = new int[26];
// Создаем буквы.
int num_letters = int.Parse(txtNumLetters.Text);
string result = "";
for (int i = 0; i < num_letters; i++)
{
// Создаем число от 0 до 100.
double num = 100.0 * Rand.NextDouble();
// См., Какую букву это представляет.
for (int letter_num = 0; ; letter_num++)
{
// Вычитаем частоту этого письма из числа.
num -= Frequencies[letter_num];
// Если num & lt; = 0, то это будет буква.
if ((num <= 0) || (letter_num == 25))
{
char ch = (char)(int_A + letter_num);
result += ch.ToString() +' ';
counts[letter_num]++;
break;
}
}
}
txtLetters.Text = result;
txtLetters.Select(0, 0);
// Отображение частот.
lstFrequencies.Items.Clear();
for (int i = 0; i < counts.Length; i++)
{
char ch = (char)(int_A + i);
float frequency = (float)counts[i] / num_letters * 100;
string str = string.Format("{0}\t{1,6}\t{2,6}\t{3,6}",
ch.ToString(),
frequency.ToString("0.000"),
Frequencies[i].ToString("0.000"),
(frequency - Frequencies[i]).ToString("0.000"));
lstFrequencies.Items.Add(str);
}
}
Для каждой из букв, которые он должен сгенерировать, программа выбирает случайное число между 0 (включительно) и 100 (исключение). Затем он перебирает значения в массиве частот, вычитая их из случайного значения. Когда случайное значение достигает 0, программа использует букву, соответствующую самой последней вычитаемой частоте. Предполагая, что Random генерирует числа с достаточно равномерным распределением (и это довольно хорошо), это означает, что каждая буква выбрана примерно с той же частотой, что и в массиве Frequencies.
