Cпособ преобразовать числовые слова в целые числа Python

Задача заключается в преобразование числовых слов в целые числа и наоборот без использования дополнительных библиотек, чистый код.

Пример:

"минус триста одиннадцать целых две десятых" -> -311,2

567.012 -> "пятьсот шестьдесят семь целых двенадцать сотых"

и т.д.


Ответы (2 шт):

Автор решения: LShadow77

Тут вообще-то принято приводить код с хотя бы минимальной попыткой решения. Тем не менее подтолкну в верном направлении: используйте табличные алгоритмы. Для ясности приведу самую простенькую программку, которая преобразует в текст целое положительное число в диапазоне от 0 до 9999 (для простоты, число вводится в виде строки).

# -*- coding: cp1251 -*-

table = (
    ("один", "два", "три", "четыре", "пять", "шесть", "семь", "восемь", "девять"),
    (None, "двадцать", "тридцать", "сорок", "пятьдесят", "шестьдесят", "семьдесят", "восемьдесят", "девяносто"),
    ("сто", "двести", "триста", "четыреста", "пятьсот", "шестьсот", "семьсот", "восемьсот", "девятьсот"),
    ("одна тысяча", "две тысячи", "три тысячи", "четыре тысячи", "пять тысяч", "шесть тысяч", "семь тысяч", "восемь тысяч", "девять тысяч")
)

table2 = ("десять", "одиннадцать", "двенадцать", "тринадцать", "четырнадцать", "пятнадцать", "шестнадцать", "семнадцать", "восемнадцать", "девятнадцать")

num = input("Введите целое положительное число: ")

text = ""
order = 0
error = 0

for c in reversed(num):
    if c==' ': continue
    if c=='0':
        order+= 1
        c1 = c
        continue
    if c>'0' and c <='9':
        if order > 3:
            print("Ошибка: число слишком большое!")
            error = 1
            break
        word = table[order][ord(c)-0x31]
        if word:
            text = word + " " + text
        else:
            text = table2[ord(c1)-0x30]
        order+= 1
        c1 = c
        continue
    print("Ошибка: посторонние символы в целом положительном числе!")
    error = 1
    break

if text=="": text = "нуль"

if not error:
    print("Введённое число: %s" %text)

Для чисел со знаком и точкой - пожалуйста, доработайте самостоятельно.

Обратная задача так же основана на таблицах. Вернее - словарях. Разбиваете входной текст на токены, такие как, например, "тысяча", "одна тысяча", "девять", "целых", "целая", и т.д., и с помощью словаря подставляете их значения (например, в виде пары (число, порядок)) и конструируете число (каким образом, придумайте сами).

В общем, идея, надеюсь, ясна? Ваяйте код))

UPD. Обновил пример кода - исправил случай с числами от 10 до 19.

→ Ссылка
Автор решения: Швеев Алексей

Слишком общий вопрос, хватит лениться, попробуй хоть что-нибудь сам сделать

Как преобразовать число, описанное словами в число, описанное цифрами?

Вот тут это можно посмотреть: https://trinket.io/python3/3ecffa94e9

Первым делом разбиваем нашу строку на токены:

tokens = input().split(" ")

Проверяем, является ли минус первым токеном:

minus = False
if tokens[0] == "минус":
  tokens = tokens[1:]
  minus = True

Разделим целую и дробную часть:

integerPart = tokens
floatPart = None
if "целых" in tokens:
    integerPart = tokens[:tokens.index("целых")]
    floatPart = tokens[tokens.index("целых")+1:-1]
    floatPartType = tokens[-1]

Любой токен можно представить в виде модификатора. Так например токен тысяч значит тысяч того, что было до него. Простые же числа просто добавляются к результату

Определим токены и то, как они влияют на число:

def add(count): return lambda x: x+count
def mul(count): return lambda x: x*count

start_tokens = [
    
    [["один", "одна"], add(1)],
    [["два"], add(2)],
    [["три"], add(3)],
    [["четыре"], add(4)],
    [["пять"], add(5)],
    [["шесть"], add(6)],
    [["семь"], add(7)],
    [["восемь"], add(8)],
    [["девять"], add(9)],
    [["десять"], add(10)],
    
    [["десятков", "десяток", "десятка"], mul(10)],
    
    [["одиннадцать"], add(11)],
    [["двенадцать"], add(12)],
    [["тринадцать"], add(13)],
    [["четырнадцать"], add(14)],
    [["пятнадцать"], add(15)],
    [["шестнадцать"], add(16)],
    [["семнадцать"], add(17)],
    [["восемнадцать"], add(18)],
    [["девятнадцать"], add(19)],
    [["двадцать"], add(20)],
    [["тридцать"], add(30)],
    [["сорок"], add(40)],
    [["пятьдесят"], add(50)],
    [["шестьдесят"], add(60)],
    [["семьдесят"], add(70)],
    [["восемьдесят"], add(80)],
    [["девяносто"], add(90)],
    [["сто"], add(100)],
    
    [["сотен", "сотни"], mul(100)],
    
    [["двести"], add(200)],
    
    [["тысяч", "тысячи"], mul(1000)],
]

Теперь надо реализовать метод для сопоставления значения:

def matchToken(token):
    for tokens in start_tokens:
        if token in tokens[0]:
            return tokens[1]

Объявляем финальный результат:

value = 0
floatValue = 0 # Вещественная часть

Проходимся по каждому токену целочисленной части:

for token in integerPart:
   value = matchToken(token)(value)

Аналогично по вещественной (если она имеется), и добавляем её в результат:

floatTypeTokens = {
    "десятых": 10,
    "сотых": 100,
    "тысячных": 1000
}

if floatPart != None:
    floatValue = 0
    for token in floatPart:
        floatValue = matchToken(token)(floatValue)
    value += floatValue / floatTypeTokens[floatPartType]

Добавляем минус при необходимости:

value *= -1 if minus else 1

Если вы хотите что бы пять шесть выдавали ошибку, то вам стоит проверять, заменяются ли в числе ТОЛЬКО нули. Если вам интересно напишите, я опишу алгоритм (код точно давать не буду)

Полный код:

def add(count): return lambda x: x+count
def mul(count): return lambda x: x*count

startTokens = [
    
  [["один", "одна"], add(1)],
  [["два"], add(2)],
  [["три"], add(3)],
  [["четыре"], add(4)],
  [["пять"], add(5)],
  [["шесть"], add(6)],
  [["семь"], add(7)],
  [["восемь"], add(8)],
  [["девять"], add(9)],
  [["десять"], add(10)],
  
  [["десятков", "десяток", "десятка"], mul(10)],
  
  [["одиннадцать"], add(11)],
  [["двенадцать"], add(12)],
  [["тринадцать"], add(13)],
  [["четырнадцать"], add(14)],
  [["пятнадцать"], add(15)],
  [["шестнадцать"], add(16)],
  [["семнадцать"], add(17)],
  [["восемнадцать"], add(18)],
  [["девятнадцать"], add(19)],
  [["двадцать"], add(20)],
  [["тридцать"], add(30)],
  [["сорок"], add(40)],
  [["пятьдесят"], add(50)],
  [["шестьдесят"], add(60)],
  [["семьдесят"], add(70)],
  [["восемьдесят"], add(80)],
  [["девяносто"], add(90)],
  [["сто"], add(100)],
  
  [["сотен", "сотни"], mul(100)],
  
  [["двести"], add(200)],
  [["триста"], add(300)],
  [["четыреста"], add(400)],
  
  [["тысяч", "тысячи"], mul(1000)],
]

floatTypeTokens = {
  "десятых": 10,
  "сотых": 100,
  "тысячных": 1000
}

def matchToken(token):
  for tokens in startTokens:
    if token in tokens[0]:
        return tokens[1]
            
while True:
  try:
    tokens = input().split(" ")
    value = 0
    
    
    minus = False
    if tokens[0] == "минус":
      tokens = tokens[1:]
      minus = True
        
    integerPart = tokens
    floatPart = None
    if "целых" in tokens:
      integerPart = tokens[:tokens.index("целых")]
      floatPart = tokens[tokens.index("целых")+1:-1]
      floatPartType = tokens[-1]
    
    for token in integerPart:
      value = matchToken(token)(value)
    
    if floatPart != None:
      floatValue = 0
      for token in floatPart:
        floatValue = matchToken(token)(floatValue)
      value += floatValue / floatTypeTokens[floatPartType]
    
    value *= -1 if minus else 1
    print(value)
  except:
    print("Error")
    

Как преобразовать число, описанное цифрами в число, описанное словами?

Интересный вопрос. На самом деле точного решения нет, ведь одно и то же число можно описать по-разному.

→ Ссылка