Как мне сказать Python преобразовать целые числа в слова - PullRequest
47 голосов
/ 24 января 2012

Я пытаюсь сказать Python преобразовать целые числа в слова.

Пример: (используя песню 99 бутылок пива на стене)

Я использовалэтот код для написания программы:

for i in range(99,0,-1):
    print i, "Bottles of beer on the wall,"
    print i, "bottles of beer."
    print "Take one down and pass it around,"
    print i-1, "bottles of beer on the wall."
    print

Но я не могу понять, как написать программу, чтобы вместо цифр отображались слова (т.е. девяносто девять, девяносто восемь и т. д.).

Я ломал голову в имеющейся у меня книге на Питоне, я понимаю, что, возможно, я просто не понимаю циклы for / if / elif / else, но я просто вращаюсьмои колеса.

Может ли кто-нибудь высказать свое мнение?Я не ищу прямого ответа, хотя это может помочь мне увидеть мою проблему, просто что-нибудь, что укажет мне правильное направление, было бы замечательно.

Ответы [ 14 ]

59 голосов
/ 30 июля 2014

Пакет inflect может сделать это.

https://pypi.python.org/pypi/inflect

$ pip install inflect

и затем:

>>>import inflect
>>>p = inflect.engine()
>>>p.number_to_words(99)
ninety-nine
34 голосов
/ 24 января 2012

Используйте модуль pynum2word , который можно найти в sourceforge

>>> import num2word
>>> num2word.to_card(15)
'fifteen'
>>> num2word.to_card(55)
'fifty-five'
>>> num2word.to_card(1555)
'one thousand, five hundred and fifty-five'
19 голосов
/ 05 октября 2013

Мы адаптировали существующее хорошее решение (ref) для преобразования чисел в слова следующим образом:

def numToWords(num,join=True):
    '''words = {} convert an integer number into words'''
    units = ['','one','two','three','four','five','six','seven','eight','nine']
    teens = ['','eleven','twelve','thirteen','fourteen','fifteen','sixteen', \
             'seventeen','eighteen','nineteen']
    tens = ['','ten','twenty','thirty','forty','fifty','sixty','seventy', \
            'eighty','ninety']
    thousands = ['','thousand','million','billion','trillion','quadrillion', \
                 'quintillion','sextillion','septillion','octillion', \
                 'nonillion','decillion','undecillion','duodecillion', \
                 'tredecillion','quattuordecillion','sexdecillion', \
                 'septendecillion','octodecillion','novemdecillion', \
                 'vigintillion']
    words = []
    if num==0: words.append('zero')
    else:
        numStr = '%d'%num
        numStrLen = len(numStr)
        groups = (numStrLen+2)/3
        numStr = numStr.zfill(groups*3)
        for i in range(0,groups*3,3):
            h,t,u = int(numStr[i]),int(numStr[i+1]),int(numStr[i+2])
            g = groups-(i/3+1)
            if h>=1:
                words.append(units[h])
                words.append('hundred')
            if t>1:
                words.append(tens[t])
                if u>=1: words.append(units[u])
            elif t==1:
                if u>=1: words.append(teens[u])
                else: words.append(tens[t])
            else:
                if u>=1: words.append(units[u])
            if (g>=1) and ((h+t+u)>0): words.append(thousands[g]+',')
    if join: return ' '.join(words)
    return words

#example usages:
print numToWords(0)
print numToWords(11)
print numToWords(110)
print numToWords(1001000025)
print numToWords(123456789012)

Результаты:

zero
eleven
one hundred ten
one billion, one million, twenty five
one hundred twenty three billion, four hundred fifty six million, seven hundred
eighty nine thousand, twelve

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

15 голосов
/ 18 сентября 2015

Вот способ сделать это в Python 3:

"""Given an int32 number, print it in English."""
def int_to_en(num):
    d = { 0 : 'zero', 1 : 'one', 2 : 'two', 3 : 'three', 4 : 'four', 5 : 'five',
          6 : 'six', 7 : 'seven', 8 : 'eight', 9 : 'nine', 10 : 'ten',
          11 : 'eleven', 12 : 'twelve', 13 : 'thirteen', 14 : 'fourteen',
          15 : 'fifteen', 16 : 'sixteen', 17 : 'seventeen', 18 : 'eighteen',
          19 : 'nineteen', 20 : 'twenty',
          30 : 'thirty', 40 : 'forty', 50 : 'fifty', 60 : 'sixty',
          70 : 'seventy', 80 : 'eighty', 90 : 'ninety' }
    k = 1000
    m = k * 1000
    b = m * 1000
    t = b * 1000

    assert(0 <= num)

    if (num < 20):
        return d[num]

    if (num < 100):
        if num % 10 == 0: return d[num]
        else: return d[num // 10 * 10] + '-' + d[num % 10]

    if (num < k):
        if num % 100 == 0: return d[num // 100] + ' hundred'
        else: return d[num // 100] + ' hundred and ' + int_to_en(num % 100)

    if (num < m):
        if num % k == 0: return int_to_en(num // k) + ' thousand'
        else: return int_to_en(num // k) + ' thousand, ' + int_to_en(num % k)

    if (num < b):
        if (num % m) == 0: return int_to_en(num // m) + ' million'
        else: return int_to_en(num // m) + ' million, ' + int_to_en(num % m)

    if (num < t):
        if (num % b) == 0: return int_to_en(num // b) + ' billion'
        else: return int_to_en(num // b) + ' billion, ' + int_to_en(num % b)

    if (num % t == 0): return int_to_en(num // t) + ' trillion'
    else: return int_to_en(num // t) + ' trillion, ' + int_to_en(num % t)

    raise AssertionError('num is too large: %s' % str(num))

И результат:

0 zero
3 three
10 ten
11 eleven
19 nineteen
20 twenty
23 twenty-three
34 thirty-four
56 fifty-six
80 eighty
97 ninety-seven
99 ninety-nine
100 one hundred
101 one hundred and one
110 one hundred and ten
117 one hundred and seventeen
120 one hundred and twenty
123 one hundred and twenty-three
172 one hundred and seventy-two
199 one hundred and ninety-nine
200 two hundred
201 two hundred and one
211 two hundred and eleven
223 two hundred and twenty-three
376 three hundred and seventy-six
767 seven hundred and sixty-seven
982 nine hundred and eighty-two
999 nine hundred and ninety-nine
1000 one thousand
1001 one thousand, one
1017 one thousand, seventeen
1023 one thousand, twenty-three
1088 one thousand, eighty-eight
1100 one thousand, one hundred
1109 one thousand, one hundred and nine
1139 one thousand, one hundred and thirty-nine
1239 one thousand, two hundred and thirty-nine
1433 one thousand, four hundred and thirty-three
2000 two thousand
2010 two thousand, ten
7891 seven thousand, eight hundred and ninety-one
89321 eighty-nine thousand, three hundred and twenty-one
999999 nine hundred and ninety-nine thousand, nine hundred and ninety-nine
1000000 one million
2000000 two million
2000000000 two billion
10 голосов
/ 24 января 2012

Ну, самый простой способ сделать это - составить список всех интересующих вас номеров:

numbers = ["zero", "one", "two", "three", "four", "five", ... 
           "ninety-eight", "ninety-nine"]

(... указывает, где вы будете вводить текстовые представления других чисел. Нет, Python не собирается волшебным образом заполнять это для вас, вам нужно будет набрать их все, чтобы использовать эту технику. )

А затем, чтобы напечатать число, просто напечатайте numbers[i]. Легкий горох.

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

numbers = "zero one two three four five six seven eight nine".split()
numbers.extend("ten eleven twelve thirteen fourteen fifteen sixteen".split())
numbers.extend("seventeen eighteen nineteen".split())
numbers.extend(tens if ones == "zero" else (tens + "-" + ones) 
    for tens in "twenty thirty forty fifty sixty seventy eighty ninety".split()
    for ones in numbers[0:10])

print numbers[42]  # "forty-two"

Другой подход - написать функцию, которая каждый раз собирает правильную строку. Опять же, вам придется жестко кодировать первые двадцать чисел, но после этого вы сможете легко сгенерировать их с нуля по мере необходимости. При этом потребляется немного меньше памяти (на много меньше, когда вы начинаете работать с большими числами).

2 голосов
/ 14 августа 2018

И вот мое решение :) Это различные из более ранних решений, но разработанные мной самим - может, кому-то понравится больше, чем другим предложениям.

TENS = {30: 'thirty', 40: 'forty', 50: 'fifty', 60: 'sixty', 70: 'seventy', 80: 'eighty', 90: 'ninety'}
ZERO_TO_TWENTY = (
    'zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten',
    'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen', 'twenty'
)

def number_to_english(n):
    if any(not x.isdigit() for x in str(n)):
        return ''

    if n <= 20:
        return ZERO_TO_TWENTY[n]
    elif n < 100 and n % 10 == 0:
        return TENS[n]
    elif n < 100:
        return number_to_english(n - (n % 10)) + ' ' + number_to_english(n % 10)
    elif n < 1000 and n % 100 == 0:
        return number_to_english(n / 100) + ' hundred'
    elif n < 1000:
        return number_to_english(n / 100) + ' hundred ' + number_to_english(n % 100)
    elif n < 1000000:
        return number_to_english(n / 1000) + ' thousand ' + number_to_english(n % 1000)

    return ''

Это рекурсивное решение, которое можно легко расширить для больших чисел

2 голосов
/ 23 августа 2017

Вы можете использовать библиотеку python-n2w , просто сделайте

pip install n2w

, затем просто

print(n2w.convert(your-number-here))
2 голосов
/ 24 апреля 2017

Вот реорганизованная версия нескольких примеров кода, размещенных выше (в основном код, вставленный разработчиком).

def int2words(num):
    """Given an int32 number, print it in English.

    Parameters
    ----------
    num : int

    Returns
    -------
    words : str
    """
    assert (0 <= num)
    d = {
        0: 'zero', 1: 'one', 2: 'two', 3: 'three', 4: 'four', 5: 'five',
        6: 'six', 7: 'seven', 8: 'eight', 9: 'nine', 10: 'ten',
        11: 'eleven', 12: 'twelve', 13: 'thirteen', 14: 'fourteen',
        15: 'fifteen', 16: 'sixteen', 17: 'seventeen', 18: 'eighteen',
        19: 'nineteen', 20: 'twenty',
        30: 'thirty', 40: 'forty', 50: 'fifty', 60: 'sixty',
        70: 'seventy', 80: 'eighty', 90: 'ninety'
    }
    h = [100, 'hundred', 'hundred and']
    k = [h[0] * 10, 'thousand', 'thousand,']
    m = [k[0] * 1000, 'million', 'million,']
    b = [m[0] * 1000, 'billion', 'billion,']
    t = [b[0] * 1000, 'trillion', 'trillion,']
    if num < 20:
        return d[num]
    if num < 100:
        div_, mod_ = divmod(num, 10)
        return d[num] if mod_ == 0 else d[div_ * 10] + '-' + d[mod_]
    else:
        if num < k[0]:
            divisor, word1, word2 = h
        elif num < m[0]:
            divisor, word1, word2 = k
        elif num < b[0]:
            divisor, word1, word2 = m
        elif num < t[0]:
            divisor, word1, word2 = b
        else:
            divisor, word1, word2 = t
        div_, mod_ = divmod(num, divisor)
        if mod_ == 0:
            return '{} {}'.format(int2words(div_), word1)
        else:
            return '{} {} {}'.format(int2words(div_), word2, int2words(mod_))
2 голосов
/ 24 января 2012

Похоже, вам нужно использовать массив, где num[1] = "one", num[2] = "two" и т. Д. Тогда вы можете просмотреть каждый, как вы уже и

num = array(["one","two","three","four","five","six","seven","eight","nine","ten"])
for i in range(10,0,-1):
    print num[i], "Bottles of beer on the wall,"
    print num[i], "bottles of beer."
    print "Take one down and pass it around,"
    print num[i-1], "bottles of beer on the wall."
    print ""
1 голос
/ 14 июня 2017

Это работает и для первых 1000 чисел (Python 3). Решение проблемы новичком, но, тем не менее, решением ...

first_nums = ["", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve",
              "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"]
tens = ["ten", "twenty", "thirty","forty","fifty", "sixty","seventy","eighty","ninety"]

for num in range(1,1001):
    if num < 20:
        print(first_nums[num])
    elif num < 100 and num % 10 == 0:
        print(tens[int(num/10 - 1)])
    elif num < 1000 and num % 100 == 0:
        print(first_nums[int(num/100)] + " hundred")
    elif num == 1000:
        print("one thousand")
    elif num < 100 and num % 10 != 0:
        print(tens[int(num//10 - 1)] + " " + first_nums[int(num%10)])
    elif num < 1000:
        if num%100 < 20:
            print(first_nums[int(num//100)] + " hundred and " + first_nums[num%100])
        else:
            print(first_nums[int(num//100)] + " hundred and " + tens[int(num%100//10 - 1)] + " " + first_nums[int(num%10)])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...