Генерация букв с заданными частотами в 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 содержатся относительные процентные частоты букв, перечисленные в
Код создает объект 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.