Exemple #1
0
        def _short_scale(n):
            if n >= max(_SHORT_SCALE_CS.keys()):
                return "nekonečno"
            ordi = ordinals

            if int(n) != n:
                ordi = False
            n = int(n)
            assert 0 <= n
            res = []
            for i, z in enumerate(_split_by(n, 1000)):
                if not z:
                    continue
                number = _sub_thousand(z, not i and ordi)

                if i:
                    if i >= len(hundreds):
                        return ""
                    number += " "
                    if ordi:

                        if i * 1000 in _SHORT_ORDINAL_CS:
                            if z == 1:
                                number = _SHORT_ORDINAL_CS[i * 1000]
                            else:
                                number += _SHORT_ORDINAL_CS[i * 1000]
                        else:
                            if n not in _SHORT_SCALE_CS:
                                num = int("1" + "0" * (len(str(n)) - 2))

                                number += _SHORT_SCALE_CS[num] + "tý"
                            else:
                                number = _SHORT_SCALE_CS[n] + "tý"
                    else:
                        number += hundreds[i]
                res.append(number)
                ordi = False

            return ", ".join(reversed(res))
Exemple #2
0
def pronounce_number_cs(num,
                        places=2,
                        short_scale=True,
                        scientific=False,
                        ordinals=False):
    """
    Convert a number to it's spoken equivalent

    For example, '5.2' would return 'five point two'

    Args:
        num(float or int): the number to pronounce (under 100)
        places(int): maximum decimal places to speak
        short_scale (bool) : use short (True) or long scale (False)
            https://en.wikipedia.org/wiki/Names_of_large_numbers
        scientific (bool): pronounce in scientific notation
        ordinals (bool): pronounce in ordinal form "first" instead of "one"
    Returns:
        (str): The pronounced number
    """
    # deal with infinity
    if num == float("inf"):
        return "nekonečno"
    elif num == float("-inf"):
        return "záp**né nekonečno"
    if scientific:
        number = '%E' % num
        n, power = number.replace("+", "").split("E")
        power = int(power)
        if power != 0:
            if ordinals:
                # This handles záp**nés of powers separately from the normal
                # handling since each call disables the scientific flag
                return '{}{} krát deset k {}{} mocnině'.format(
                    'záp**né ' if float(n) < 0 else '',
                    pronounce_number_cs(abs(float(n)),
                                        places,
                                        short_scale,
                                        False,
                                        ordinals=False),
                    'záp**né ' if power < 0 else '',
                    pronounce_number_cs(abs(power),
                                        places,
                                        short_scale,
                                        False,
                                        ordinals=True))
            else:
                # This handles záp**nés of powers separately from the normal
                # handling since each call disables the scientific flag
                return '{}{} krát deset na mocninu {}{}'.format(
                    'záp**né ' if float(n) < 0 else '',
                    pronounce_number_cs(abs(float(n)), places, short_scale,
                                        False),
                    'záp**né ' if power < 0 else '',
                    pronounce_number_cs(abs(power), places, short_scale,
                                        False))

    if short_scale:
        number_names = _NUM_STRING_CS.copy()
        number_names.update(_SHORT_SCALE_CS)
    else:
        number_names = _NUM_STRING_CS.copy()
        number_names.update(_LONG_SCALE_CS)

    digits = [number_names[n] for n in range(0, 20)]

    tens = [number_names[n] for n in range(10, 100, 10)]

    if short_scale:
        hundreds = [_SHORT_SCALE_CS[n] for n in _SHORT_SCALE_CS.keys()]
    else:
        hundreds = [_LONG_SCALE_CS[n] for n in _LONG_SCALE_CS.keys()]

    # deal with záp**nés
    result = ""
    if num < 0:
        result = "záp**né " if scientific else "mínus "
    num = abs(num)

    if not ordinals:
        try:
            # deal with 4 digits
            # usually if it's a 4 digit num it should be said like a date
            # i.e. 1972 => nineteen seventy two
            if len(str(num)) == 4 and isinstance(num, int):
                _num = str(num)
                # deal with 1000, 2000, 2001, 2100, 3123, etc
                # is skipped as the rest of the
                # functin deals with this already
                if _num[1:4] == '000' or _num[1:3] == '00' or int(
                        _num[0:2]) >= 20:
                    pass
                # deal with 1900, 1300, etc
                # i.e. 1900 => nineteen hundred
                elif _num[2:4] == '00':
                    first = number_names[int(_num[0:2])]
                    last = number_names[100]
                    return first + " " + last
                # deal with 1960, 1961, etc
                # i.e. 1960 => nineteen sixty
                #      1961 => nineteen sixty one
                else:
                    first = number_names[int(_num[0:2])]
                    if _num[3:4] == '0':
                        last = number_names[int(_num[2:4])]
                    else:
                        second = number_names[int(_num[2:3]) * 10]
                        last = second + " " + number_names[int(_num[3:4])]
                    return first + " " + last
        # exception used to catch any unforseen edge cases
        # will default back to normal subroutine
        except Exception as e:
            print('ERROR: Exception in pronounce_number_cs: {}' + repr(e))

    # check for a direct match
    if num in number_names and not ordinals:
        if num > 90:
            result += "jedna "
        result += number_names[num]
    else:

        def _sub_thousand(n, ordinals=False):
            assert 0 <= n <= 999
            if n in _SHORT_ORDINAL_CS and ordinals:
                return _SHORT_ORDINAL_CS[n]
            if n <= 19:
                return digits[n]
            elif n <= 99:
                q, r = divmod(n, 10)
                return tens[q - 1] + (" " +
                                      _sub_thousand(r, ordinals) if r else "")
            else:
                q, r = divmod(n, 100)
                return digits[q] + " sto" + (
                    " a " + _sub_thousand(r, ordinals) if r else "")

        def _short_scale(n):
            if n >= max(_SHORT_SCALE_CS.keys()):
                return "nekonečno"
            ordi = ordinals

            if int(n) != n:
                ordi = False
            n = int(n)
            assert 0 <= n
            res = []
            for i, z in enumerate(_split_by(n, 1000)):
                if not z:
                    continue
                number = _sub_thousand(z, not i and ordi)

                if i:
                    if i >= len(hundreds):
                        return ""
                    number += " "
                    if ordi:

                        if i * 1000 in _SHORT_ORDINAL_CS:
                            if z == 1:
                                number = _SHORT_ORDINAL_CS[i * 1000]
                            else:
                                number += _SHORT_ORDINAL_CS[i * 1000]
                        else:
                            if n not in _SHORT_SCALE_CS:
                                num = int("1" + "0" * (len(str(n)) - 2))

                                number += _SHORT_SCALE_CS[num] + "tý"
                            else:
                                number = _SHORT_SCALE_CS[n] + "tý"
                    else:
                        number += hundreds[i]
                res.append(number)
                ordi = False

            return ", ".join(reversed(res))

        def _split_by(n, split=1000):
            assert 0 <= n
            res = []
            while n:
                n, r = divmod(n, split)
                res.append(r)
            return res

        def _long_scale(n):
            if n >= max(_LONG_SCALE_CS.keys()):
                return "nekonečno"
            ordi = ordinals
            if int(n) != n:
                ordi = False
            n = int(n)
            assert 0 <= n
            res = []
            for i, z in enumerate(_split_by(n, 1000000)):
                if not z:
                    continue
                number = pronounce_number_cs(z,
                                             places,
                                             True,
                                             scientific,
                                             ordinals=ordi and not i)
                # strip off the comma after the thousand
                if i:
                    if i >= len(hundreds):
                        return ""
                    # plus one as we skip 'thousand'
                    # (and 'hundred', but this is excluded by index value)
                    number = number.replace(',', '')

                    if ordi:
                        if i * 1000000 in _LONG_ORDINAL_CS:
                            if z == 1:
                                number = _LONG_ORDINAL_CS[(i + 1) * 1000000]
                            else:
                                number += _LONG_ORDINAL_CS[(i + 1) * 1000000]
                        else:
                            if n not in _LONG_SCALE_CS:
                                num = int("1" + "0" * (len(str(n)) - 2))

                                number += " " + _LONG_SCALE_CS[num] + "tý"
                            else:
                                number = " " + _LONG_SCALE_CS[n] + "tý"
                    else:

                        number += " " + hundreds[i + 1]
                res.append(number)
            return ", ".join(reversed(res))

        if short_scale:
            result += _short_scale(num)
        else:
            result += _long_scale(num)

    # deal with scientific notation unpronounceable as number
    if not result and "e" in str(num):
        return pronounce_number_cs(num, places, short_scale, scientific=True)
    # Deal with fractional part
    elif not num == int(num) and places > 0:
        if abs(num) < 1.0 and (result is "mínus " or not result):
            result += "nula"
        result += " tečka"
        _num_str = str(num)
        _num_str = _num_str.split(".")[1][0:places]
        for char in _num_str:
            result += " " + number_names[int(char)]
    return result