Склонение по падежам на C# / VB.NET
Morpher.dll – это .NET библиотека, реализующая функции склонения по падежам, автоматического определения рода словосочетания и
прописи чисел на русском языке.
Пример программы на C#
Вот пример кода для формирования текста, в котором одно и то же ФИО фигурирует в разных падежах:
class HelloIvanIvanych
{
static void Main ()
{
Склонятель склонятель = new Склонятель ();
IСклоняемое получатель =
склонятель.Проанализировать ("Иванов Иван Иваныч");
string справка = @"
СПРАВКА
Выдана {0} в том, что
{1} было получено разрешение
о том, что {2} не нуждается
более в получении никаких справок.";
System.Console.WriteLine (
справка,
получатель.Дательный,
получатель.Творительный,
получатель.Именительный);
}
}
Да, это C# – он допускает использование русских букв в именах переменных и классов.
Программа выдаёт в консольное окно следующий текст:
СПРАВКА
Выдана Иванову Ивану Иванычу в том, что
Ивановым Иваном Иванычем было получено разрешение
о том, что Иванов Иван Иваныч не нуждается
более в получении никаких справок.
Функция склонения
Склонение производится за три этапа:
- Создание экземпляра класса Склонятель.
- Вызов метода Проанализировать.
- Чтение одного из свойств интерфейса IСклоняемое
для получения формы нужного падежа.
Вы можете спросить, зачем такие сложности? Почему бы не сделать API в виде одной функции:
string Просклонять (string s, Падеж падеж);
Это сделано для улучшения быстродействия.
Первый этап – создание экземпляра класса Склонятель –
включает в себя загрузку словаря в память и занимает 100-200 миллисекунд.
Вроде бы немного, но в помещать эту операцию в цикл не стоит.
Второй этап – анализ – относительно сложный процесс, который включает в себя поиск по словарю и анализ синтаксической структуры словосочетания.
Результат этого анализа, объект IСклоняемое, используется на третьем, последнем, этапе для генерации форм различных падежей единственного и множественного числа.
Если необходимо генерировать несколько падежных форм, как в примере выше, то время экономится, т.к. анализ проводится всего один раз.
Знание этих особенностей позволяет сделать программу молниеносной.
Приведу пример. Для контроля качества склонения алгоритма Morpher.dll используется база тестов,
где каждый тест состоит из трех частей:
- пример словосочетания в именительном падеже
- идентификатор падежа
- «правильный ответ» – как это словосочетание должно выглядеть в данном падеже.
Все тесты были составлены вручную. Я постоянно экспериментирую с алгоритмом склонения и каждый раз, внося изменения в в программу,
прогоняю все тесты, чтобы быть уверенным, что качество склонения не ухудшилось.
На данный момент (1 сентября 2011 г.) объем базы составляет более 18 тысяч тестов.
Поэтому мне важно, чтобы тесты прогонялись как можно быстрее.
Теперь внимание, вопрос! Как вы думаете, сколько времени занимает прогон всех тестов?
Подсказка
Подсказка:
Тестовая программа использует все 4 ядра моего ноутбука.
Ответ
Ответ:
628 миллисекунд.
Размер DLL 450K.
Код библиотеки полностью написан на C# и не имеет никаких внешних зависимостей.
Библиотека не имеет интерфейса пользователя и не требует прав доступа к диску или сети.
Все public методы библиотеки потокобезопасны, что особенно актуально при её использовании
в серверных приложениях.
Функция прописи чисел в заданном падеже
string Пропись (int n, ref string unit, Падеж падеж = Падеж.Именительный);
Возвращает пропись числа n, например, «сто двадцать пять».
Параметры:
n – число, пропись которого строится. Должно быть положительным, иначе функция выбрасывает ArgumentException.
Ноль намеренно не включен в диапазон допустимых значений.
Есть также перегруженный вариант метода для типа decimal.
unit – единица измерения – слово или словосочетание на русском языке в именительном падеже единственного числа: «рубль», «доллар США», «календарный день», «новое письмо» и т.п. Если слово употребляется только во множественном числе, то указывается форма именительного падежа множественного числа: «сутки», «брюки», «ножницы».
падеж – при указании падежа пропись и единица измерения ставятся в заданный падеж.
Единица измерения (unit) склоняется в большинстве случаев, даже если указан именительный падеж,
как того требуют правила русского языка: «один рубль», «три рубля», «пять рублей», «пяти рублям», «пяти рублей» и т.п.
Результат возвращается через тот же параметр unit (для этого указан модификатор ref).
Примеры:
Пример 1. Пропись в рублях
string Прописью (int n, string unit)
{
return склонятель.Пропись (n, ref unit) + " " + unit;
}
Console.WriteLine (Прописью (100, "рубль")); //
Console.WriteLine (Прописью (101, "рубль")); //
Console.WriteLine (Прописью (102, "рубль")); //
Пример 2. Цена договора с НДС
string ПрописьРуб (Падеж падеж, int n)
{
string unit = "рубль"; return n + " (" + склонятель.Пропись (n, ref unit, падеж) + ") " + unit;
}
int цена = 1800;
Console.Write ("Цена договора составляет {0}, ", ПрописьРуб (Падеж.Винительный, цена));
Console.Write ("в том числе НДС в размере {0}.", ПрописьРуб (Падеж.Родительный, (int) (цена * 0.18 / 1.18)));
Пример 3. Перечень товаров
var товары = new []
{
new {Наименование = "шампур из нержавеющей стали", Количество = 12},
new {Наименование = "решетка-гриль", Количество = 2},
new {Наименование = "щипцы для углей", Количество = 1},
};
foreach (var товар in товары)
{
Console.WriteLine ("{0,-30} {1,2} ({2})",
товар.Наименование,
товар.Количество,
склонятель.Пропись (товар.Количество, товар.Наименование));
}
Для таких случаев, как этот – когда не нужно выводить единицу измерения после числа – предусмотрена перегрузка метода без ref.
(Сам не знал, что можно перегружать по ref, но оказывается можно, и это здесь очень пригодилось.)
Пример 4. Социальная сеть
string Новых (string unit, int n)
{
switch (склонятель.Проанализировать (unit).РодЧисло)
{
case РодЧисло.ЕдинМуж: unit = "новый " + unit; break;
case РодЧисло.ЕдинЖен: unit = "новая " + unit; break;
case РодЧисло.ЕдинСред: unit = "новое " + unit; break;
case РодЧисло.Множ: unit = "новые " + unit; break;
}
склонятель.Пропись (n, ref unit);
return n + " " + unit;
}
Console.WriteLine ("У вас " + Новых ("друг", 5));
Console.WriteLine ("У вас " + Новых ("сообщение", 1));
Console.WriteLine ("У вас " + Новых ("подарок", 2));
Пример 5. День рождения
string Исполнилось (string кто, int сколько)
{
string unit = "год";
склонятель.Пропись (сколько, ref unit);
return склонятель.Проанализировать (кто).Дательный
+ " " + сколько + " " + unit;
}
Console.WriteLine (Исполнилось ("Анечка", 2));
Console.WriteLine (Исполнилось ("Вовочка", 5));
Console.WriteLine (Исполнилось ("Иван Иванович", 51));
Console.WriteLine (Исполнилось ("мы", 10));
Попробуйте функцию «Пропись» в действии на сайте summa-pro.ru.
Facebook Story
Facebook Story – это пример программы на C# для генерации параллельных текстов на двух языках, русском и английском, с использованием механизма регулярных выражений и конечно же,
функций склонения из библиотеки Morpher.dll.
Скачать пример: FacebookStory.zip
Купить библиотеку Morpher.dll
Комментарии