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 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