-2

Is there a way to get the text equivalent of a number in Python? I've added a little script as a suggested answer, but I don't know if there should be commata or hyphens in it. I was hoping for a standard library version, like there is for, say, month names.

Ion Freeman
  • 512
  • 4
  • 19
  • 2
    Have you checked num2words? https://pypi.org/project/num2words/ – scmanjarrez Apr 29 '22 at 21:10
  • 1
    Does this is answer for this one https://stackoverflow.com/questions/8982163/how-do-i-tell-python-to-convert-integers-into-words – codester_09 Apr 29 '22 at 21:12
  • I think my real struggle was finding search terms to locate an answer. Any combination of integer, name, convert, text, string, written version... that all refers to stuff you do more often. – Ion Freeman May 02 '22 at 14:43
  • @sr-s num2words looks like exactly what I was looking for. Thanks! – Ion Freeman May 02 '22 at 14:58

1 Answers1

0
class NumberNamer:
    # try to reproduce num2words as adding that library isn't a fight I want to have https://pypi.org/project/num2words/
    single_digit_names = ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', ]
    teen_names = ['ten', 'eleven', 'twelve', 'thirteen', None, 'fifteen', ]
    tens_label = {2: 'twenty', 3: 'thirty', 4: 'forty', 5: 'fifty', 6: 'sixty', 7: 'seventy', 8: 'eighty',
                  9: 'ninety'}
    power_labels = [(1, 'thousand'), (2, 'million'), (3, 'billion'), (4, 'trillion'), (5, 'quadrillion'),
                    (7, 'ERROR')]

    @classmethod
    def to_name(cls, val: int) -> str:
        """
        Convert a number to its name 1 -> one; 37 -> thirty-seven
        :param val: number
        :return:    name of number
        """
        if val < 0:
            return f"negative {cls.to_name(-val)}"
        td = int(val / 10) % 10
        od = val % 10
        ones = cls.single_digit_names[od]
        # interpret the tens digit
        if td == 0:
            tens = ones
        elif td == 1:
            if od != 4 and od < len(cls.teen_names):
                tens = cls.teen_names[od]
            elif od == 8:
                tens = f'{ones}een'
            else:
                tens = f'{ones}teen'
        else:
            tens = cls.tens_label[td]
            if od > 0:
                tens = f'{tens}-{ones}'
        if val < 100:
            return tens
        hd = int(val / 100) % 10
        name = f'{cls.to_name(hd)} hundred {tens}'
        for power, label in cls.power_labels:
            if val < pow(1000, power):
                return name
            digits = int(val / pow(1000, power)) % 1000
            name = f"{cls.to_name(digits)} {label}, {name}"
        raise Exception(f"{val} too big, concocted {name} and gave up")

nn = NumberNamer()
for xmpl in list(range(-20, 20)) + [37, 84, 295, 43823, 3438821, 95234098191, 458741684687387373,
                                    6473743453546436874374347354]:
    print(nn.to_name(xmpl))
Ion Freeman
  • 512
  • 4
  • 19