-
Notifications
You must be signed in to change notification settings - Fork 0
/
num2text.py
141 lines (122 loc) · 4.13 KB
/
num2text.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# -*- coding: utf-8 -*-
'''
Created on 04.07.2011
Changed on 13.03.2016 by Artem Tiumentcev
@author: Sergey Prokhorov <me@seriyps.ru>
'''
import decimal
units = (
u'ноль',
(u'один', u'одна'),
(u'два', u'две'),
u'три', u'четыре', u'пять',
u'шесть', u'семь', u'восемь', u'девять'
)
teens = (
u'десять', u'одиннадцать',
u'двенадцать', u'тринадцать',
u'четырнадцать', u'пятнадцать',
u'шестнадцать', u'семнадцать',
u'восемнадцать', u'девятнадцать'
)
tens = (
teens,
u'двадцать', u'тридцать',
u'сорок', u'пятьдесят',
u'шестьдесят', u'семьдесят',
u'восемьдесят', u'девяносто'
)
hundreds = (
u'сто', u'двести',
u'триста', u'четыреста',
u'пятьсот', u'шестьсот',
u'семьсот', u'восемьсот',
u'девятьсот'
)
orders = (# plural forms and gender
#((u'', u'', u''), 'm'), # ((u'рубль', u'рубля', u'рублей'), 'm'), # ((u'копейка', u'копейки', u'копеек'), 'f')
((u'тысяча', u'тысячи', u'тысяч'), 'f'),
((u'миллион', u'миллиона', u'миллионов'), 'm'),
((u'миллиард', u'миллиарда', u'миллиардов'), 'm'),
)
minus = u'минус'
def thousand(rest, sex):
"""Converts numbers from 19 to 999"""
prev = 0
plural = 2
name = []
use_teens = rest % 100 >= 10 and rest % 100 <= 19
if not use_teens:
data = ((units, 10), (tens, 100), (hundreds, 1000))
else:
data = ((teens, 10), (hundreds, 1000))
for names, x in data:
cur = int(((rest - prev) % x) * 10 / x)
prev = rest % x
if x == 10 and use_teens:
plural = 2
name.append(teens[cur])
elif cur == 0:
continue
elif x == 10:
name_ = names[cur]
if isinstance(name_, tuple):
name_ = name_[0 if sex == 'm' else 1]
name.append(name_)
if cur >= 2 and cur <= 4:
plural = 1
elif cur == 1:
plural = 0
else:
plural = 2
else:
name.append(names[cur-1])
return plural, name
def num2text(num, main_units=((u'', u'', u''), 'm')):
"""
http://ru.wikipedia.org/wiki/Gettext#.D0.9C.D0.BD.D0.BE.D0.B6.D0.B5.D1.81.\
D1.82.D0.B2.D0.B5.D0.BD.D0.BD.D1.8B.D0.B5_.D1.87.D0.B8.D1.81.D0.BB.D0.B0_2
"""
_orders = (main_units,) + orders
if num == 0:
return ' '.join((units[0], _orders[0][0][2])).strip() # ноль
rest = abs(num)
ord = 0
name = []
while rest > 0:
plural, nme = thousand(rest % 1000, _orders[ord][1])
if nme or ord == 0:
name.append(_orders[ord][0][plural])
name += nme
rest = int(rest / 1000)
ord += 1
if num < 0:
name.append(minus)
name.reverse()
return ' '.join(name).strip()
def decimal2text(value, places=2,
int_units=(('', '', ''), 'm'),
exp_units=(('', '', ''), 'm')):
value = decimal.Decimal(value)
q = decimal.Decimal(10) ** -places
integral, exp = str(value.quantize(q)).split('.')
return u'{} {}'.format(
num2text(int(integral), int_units),
num2text(int(exp), exp_units))
if __name__ == '__main__':
import sys
if len(sys.argv) > 1:
try:
num = sys.argv[1]
if '.' in num:
print(decimal2text(
decimal.Decimal(num),
int_units=((u'штука', u'штуки', u'штук'), 'f'),
exp_units=((u'кусок', u'куска', u'кусков'), 'm')))
else:
print(num2text(
int(num),
main_units=((u'штука', u'штуки', u'штук'), 'f')))
except ValueError:
print (sys.stderr, "Invalid argument {}".format(sys.argv[1]))
sys.exit()