13 ноября 2012 в 13:01

Генерация числа прописью из любого произвольного числа из песочницы

Как-то раз мне понадобилось написать генерацию суммы прописью для одного проекта. Поиск готовых решений ни к чему не привел, в результате родился маленький С++ класс, генерирующий прописной эквивалент числа. В качестве приятного бонуса я добавил туда поддержу рублей и долларов (это требовалось для того проекта). Под катом немного теории и ссылка на Git-репозиторий.

Теория

Названия чисел

В русском языке числа от 1 до 9 (так называемые единицы) и от 10 до 20 (второй ряд единиц) имеют индивидуальные названия. После 20 индивидуальные названия имеют десятки, а число образуется путем прибавления к названию десятки числа категории из категории единиц.

Пример:
  • 5 — пять
  • 17 — семнадцать
  • 23 — двадцать три
  • 48 — сорок восемь


Сотни включают в себя десятки и единицы, а тысячи содержат в себе все вышеперечисленные названия. И так по мере нарастания порядка числа, то есть каждый новый порядок включает в себя все предыдущие.

Женский и мужской род названий порядков

Тут есть следующая особенность. При формировании числа меньше 100 проблем нет, но при формировании прописного эквивалента больших сумм у вас появляются слова, обозначающие порядки сотен, десятов и единиц, а именно тысячи, миллионы и т.д.

Возникают такие варианты чисел:
  • одна тысяча
  • один миллион
  • два миллиона
  • две тысячи
  • пять тысяч

и т.п.

Правила такие:
  1. Для названий порядков женского рода приходится модифицировать 1 и 2 (одна, две);
  2. Для обоих родов по-разному склоняются окончания названий порядков для числа 1, группы от 2 до 4 и далее до 20 (включая второй ряд единиц от 11 до 19).


Пример:
  • 1 (одна) тысяча
  • 2-3-4 тысячи
  • 5-19 тысяч

  • 1 миллион
  • 2-3-4 миллиона
  • 5-20 миллионов


Зная эти особенности, мжно составить логику работы генератора прописного числа.

Класс

Механизм генерации числа работает следующим образом:

  1. Получив на входе число, определяем разряд числа (миллионы, тысячи или меньше);
  2. Для каждого порядка кроме генерируем сотни, десятки и единицы, дописывая в конце название порядка.


Так и родился C++ класс Propis. Из double значения на выходе получается строка с прописным значением и валютой числа (при наличии) с точностью до сотых. Реализована генерация чисел до 1 миллиарда, при необходимости можно легко сделать поддержку миллиардов и выше. Зависит только от стандартной библиотеки cmath и std::string.

Пример использования в C++ коде:
Propis *propis = new Propis;
double value = 345.12;

// Задаем число для генерации и тип валюты
std::string resultString = propis->conv(value, Propis::Dollar);
// "триста сорок пять долларов, двенадцать центов"


Пример использования в iOS-программе:
- (IBAction)valueChanged:(UITextField *)sender
{
    Propis propis;
    double value = [sender.text doubleValue];
    
    std::string stdResultString = propis.conv(value, Propis::NoCurrency);
    
    NSString *resultString = [NSString stringWithUTF8String:stdResultString.c_str()];
    
    self.resultView.text = resultString;
}


Git-репозиторий с исходным кодом класса находится здесь. Буду рад если кому-то пригодится.
Павел @mrpeabody
карма
1,0
рейтинг 0,0
Похожие публикации
Самое читаемое Разработка

Комментарии (9)

  • +1
    Судя по коду миллиарды в пролете?
  • +4
    Боже, помогите мне развидеть этот код.
    • 0
      Да, старый код, написанный впопыхах. Тем не менее, вполне рабочий и может быть кому-то пригодится
      • 0
        Лично мне было бы стыдно выкладывать ТАКОЕ на общественное обозрение.
        • 0
          Не вижу ничего стыдного если кто-то сможет воспользоваться, сэкономив себе время. Не было цели переписывать или улучшать старый код. Свою задачу он выполнил, на том спасибо. Любой программист время от времени пишет такой код, вопрос — пылиться ему на винте или же кому-то принести пользу
          • 0
            Извините, Вы видели свой код? Вы всерьез полагаете что этим можно пользоваться? При просмотре кода у меня потекли кровавые слезы. А что если где то в недрах этого чудовища проявится баг? Вы думаете что такой код можно отладить?
            Если необходим подобный функционал, то проще воспользоваться нормальной библиотекой, как например, ниже писал ragesteel.
            • 0
              Код — ужасен. Отлаживать — трудно. Но если нужна генерация русской строки, вполне подойдет, если нет желания добавлять зависимость от довольно крупной либы в проект.
  • +2
    А почему бы не воспользоваться icu-project.org, где всё это есть и не только для русского языка?
  • 0
    Кстати, а в английском языке все попроще: есть много способов на SO.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.