Преобразование числовых значений в текст средствами Python
Преобразование чисел в слова в Python: обзор методов
При работе с текстовыми отчетами, документами или платежными поручениями часто требуется представить число в виде словесной формы на русском языке. В Python существует несколько способов решить эту задачу: от использования специализированных библиотек до написания собственной логики. В данном материале рассматриваются основные подходы, их достоинства и ограничения.
Как сделать преобразование чисел в слова с помощью готовой библиотеки num2words?
Наиболее эффективное и рекомендуемое решение - библиотека num2words. Она поддерживает множество языков, включая русский, целые, дробные, порядковые числительные и валюты. Установка выполняется через pip:
pip install num2wordsPython среднее число (вычисление среднего числа в python)
После установки импортируем функцию num2words:
from num2words import num2words
# Целое число
print(num2words(123, lang='ru')) # сто двадцать три
# Дробное число
print(num2words(123.45, lang='ru')) # сто двадцать три целых сорок пять сотых
# Порядковое числительное
print(num2words(21, lang='ru', to='ordinal')) # двадцать первый
# Валюта (рубли, копейки)
print(num2words(1234.56, lang='ru', to='currency', currency='RUB')) # одна тысяча двести тридцать четыре рубля пятьдесят шесть копеекAbs x python (функция abs() в python)
Пояснение шагов:
- Параметр lang='ru' активирует русскую локализацию.
- Параметр to='ordinal' переводит число в порядковую форму.
- Параметр to='currency' вместе с указанием валюты (RUB) выводит денежную сумму прописью.
Возможные проблемы и их решение:
- Библиотека не обрабатывает отрицательные числа напрямую. Решение - перед вызовом взять модуль числа и добавить слово «минус».
- Для очень больших чисел (>10^30) могут потребоваться дополнительные настройки или усечение разрядов.
- Если библиотека не установлена или установлена старая версия, возможны ошибки импорта. Обновление: pip install --upgrade num2words.
Цель использования: быстрая и надёжная конвертация чисел в текст с минимальным кодом. Подходит для финансовых документов, чеков, автоматического формирования текстов.
Как сделать преобразование чисел в слова с учётом падежа с помощью pymorphy2?
Иногда требуется не просто написать число словами, но и просклонять его по падежам (например, «сто двадцати трёх»). Для этого используется библиотека pymorphy2 в связке с базовым разложением числа на слова.
pip install pymorphy2 num2words
Python найти максимальное значение (поиск максимального значения в python)
Пример склонения в родительном падеже:
from num2words import num2words
import pymorphy2
morph = pymorphy2.MorphAnalyzer(lang='ru')
number = 123
words = num2words(number, lang='ru').split() # ['сто', 'двадцать', 'три']
inflected = [morph.parse(word)[0].inflect({'gent'}).word for word in words]
print(' '.join(inflected)) # ста двадцати трёхчисла словами python (преобразование чисел в слова в python)
Пояснение:
- Сначала получаем словесное представление каждого слова через num2words.
- Для каждого слова выбираем форму в родительном падеже ('gent').
- Объединяем результат в строку.
Типичные ошибки:
- pymorphy2 может не распознать некоторые числительные (например, «девяносто» склоняется правильно, а «сорок» - с ошибками). Рекомендуется проверять результат для каждого числа.
- Порядковые числительные (первый, второй) склоняются по другой схеме - их лучше обрабатывать отдельно, используя num2words с to='ordinal' и затем склонять.
Цель использования: точное склонение числительных для подстановки в предложения (например, «у ста двадцати трёх участников»).
Как сделать преобразование чисел в слова без внешних библиотек (собственная реализация)?
Для учебных целей или когда нельзя устанавливать сторонние пакеты, пишется функция, разбивающая число на разряды (единицы, десятки, сотни, тысячи, миллионы). Ниже приведён упрощённый вариант для целых чисел до 999 999:
def number_to_words(n):
units = ['', 'один', 'два', 'три', 'четыре', 'пять', 'шесть', 'семь', 'восемь', 'девять']
teens = ['десять', 'одиннадцать', 'двенадцать', 'тринадцать', 'четырнадцать', 'пятнадцать', 'шестнадцать', 'семнадцать', 'восемнадцать', 'девятнадцать']
tens = ['', '', 'двадцать', 'тридцать', 'сорок', 'пятьдесят', 'шестьдесят', 'семьдесят', 'восемьдесят', 'девяносто']
hundreds = ['', 'сто', 'двести', 'триста', 'четыреста', 'пятьсот', 'шестьсот', 'семьсот', 'восемьсот', 'девятьсот']
thousands = ['', 'тысяча', 'тысячи', 'тысяч']
millions = ['', 'миллион', 'миллиона', 'миллионов']
if n == 0:
return 'ноль'
def under_1000(num, is_thousand=False):
result = ''
h = num // 100
r = num % 100
result += hundreds[h] + ' '
if 10 <= r <= 19:
result += teens[r-10] + ' '
else:
d = r // 10
u = r % 10
result += tens[d] + ' '
if is_thousand and u == 1:
result += 'одна '
elif is_thousand and u == 2:
result += 'две '
else:
result += units[u] + ' '
return result.strip()
# разбиение на миллионы и тысячи
millions_part = n // 1000000
thousands_part = (n % 1000000) // 1000
units_part = n % 1000
words = ''
if millions_part:
words += under_1000(millions_part) + ' '
# склонение слова 'миллион'
if millions_part % 10 == 1 and millions_part % 100 != 11:
words += 'миллион '
elif 2 <= millions_part % 10 <= 4:
words += 'миллиона '
else:
words += 'миллионов '
if thousands_part:
words += under_1000(thousands_part, is_thousand=True) + ' '
if thousands_part % 10 == 1 and thousands_part % 100 != 11:
words += 'тысяча '
elif 2 <= thousands_part % 10 <= 4:
words += 'тысячи '
else:
words += 'тысяч '
if units_part:
words += under_1000(units_part)
return words.strip()
print(number_to_words(123456)) # сто двадцать три тысячи четыреста пятьдесят шесть
Пояснение ключевых моментов:
- Для тысяч используются особые формы: «одна тысяча» (вместо «один тысяча»), «две тысячи».
- Каждый разряд (сотни, десятки, единицы) обрабатывается отдельно, учитывается склонение тысяч и миллионов.
- Функция не обрабатывает дроби и порядковые числительные.
Проблемы самописной реализации:
- Сложность поддержки склонений для разных падежей.
- Ошибки в числительных «сорок», «девяносто», «сто» - они имеют свои особенности.
- Ограниченный диапазон (до миллионов; для миллиардов требуется дополнительная логика).
Цель использования: понимание алгоритма, работа в изолированной среде без доступа к внешним пакетам.
Расширенные примеры преобразования чисел в слова
В этом разделе приведены более сложные и нестандартные сценарии использования.
Пример 1. Сумма прописью с копейками в разных падежах
Показывает, как вывести сумму (рубли и копейки) в родительном падеже.
from num2words import num2words
import pymorphy2
morph = pymorphy2.MorphAnalyzer(lang='ru')
amount = 1234.56
# Получаем рубли и копейки
rub = int(amount)
cop = int(round((amount - rub) * 100))
# Словесная часть рублей в именительном падеже
rub_words = num2words(rub, lang='ru')
# Копейки в именительном (целое число)
cop_words = num2words(cop, lang='ru')
# Склоняем рубли в родительный падеж (gent)
inflected_rub = ' '.join(morph.parse(w)[0].inflect({'gent'}).word if morph.parse(w)[0].tag.POS == 'NUMR' else w for w in rub_words.split())
print(f"{inflected_rub} рублей {cop_words} копеек")
# Результат: одной тысячи двухсот тридцати четырех рублей пятьдесят шесть копеек
одной тысячи двухсот тридцати четырех рублей пятьдесят шесть копеек
Пояснение: Для склонения числительных используется pymorphy2. Проверяется, что слово является числительным (POS == 'NUMR'), иначе оставляется без изменений (например, «рублей» не склоняется, хотя в данном примере мы написали «рублей» уже в родительном).
Пример 2. Работа с отрицательными числами
Библиотека num2words не поддерживает отрицательные числа. Добавляем минус вручную.
from num2words import num2words
number = -42
if number < 0:
result = 'минус ' + num2words(abs(number), lang='ru')
else:
result = num2words(number, lang='ru')
print(result) # минус сорок два
минус сорок два
Пример 3. Порядковые числительные в разных падежах (дат. п.)
from num2words import num2words
import pymorphy2
morph = pymorphy2.MorphAnalyzer(lang='ru')
number = 21
ordinal_words = num2words(number, lang='ru', to='ordinal') # 'двадцать первый'
# Разбиваем и склоняем всю фразу в дательный падеж (datv)
inflected = []
for word in ordinal_words.split():
parsed = morph.parse(word)[0]
# Склоняем, если возможно
inflected_form = parsed.inflect({'datv'})
if inflected_form:
inflected.append(inflected_form.word)
else:
inflected.append(word)
print(' '.join(inflected)) # двадцать первому
двадцать первому
Пример 4. Большие числа (миллиарды и триллионы)
num2words автоматически обрабатывает миллиарды, триллионы и т.д. для русского языка.
from num2words import num2words
print(num2words(1234567890123, lang='ru'))
один триллион двести тридцать четыре миллиарда пятьсот шестьдесят семь миллионов восемьсот девяносто тысяч сто двадцать три
Пример 5. Обработка некорректного ввода
from num2words import num2words
def safe_num2words(value):
try:
num = float(value)
if num != num: # проверка на NaN
raise ValueError
return num2words(num, lang='ru')
except (ValueError, OverflowError):
return "Ошибка: введите корректное число"
print(safe_num2words("abc")) # Ошибка
print(safe_num2words("123.45")) # сто двадцать три целых сорок пять сотых
Ошибка: введите корректное число сто двадцать три целых сорок пять сотых