mirror of
https://github.com/bblaz/num2words.git
synced 2025-12-06 14:52:25 +00:00
Merge branch 'master' into master
This commit is contained in:
@@ -31,6 +31,9 @@ from . import lang_ID
|
||||
from . import lang_NO
|
||||
from . import lang_DK
|
||||
from . import lang_PT_BR
|
||||
from . import lang_HE
|
||||
from . import lang_IT
|
||||
from . import lang_VN
|
||||
|
||||
CONVERTER_CLASSES = {
|
||||
'en': lang_EN.Num2Word_EN(),
|
||||
@@ -48,6 +51,9 @@ CONVERTER_CLASSES = {
|
||||
'no': lang_NO.Num2Word_NO(),
|
||||
'dk': lang_DK.Num2Word_DK(),
|
||||
'pt_BR': lang_PT_BR.Num2Word_PT_BR(),
|
||||
'he': lang_HE.Num2Word_HE(),
|
||||
'it': lang_IT.Num2Word_IT(),
|
||||
'vi_VN': lang_VN.Num2Word_VN()
|
||||
}
|
||||
|
||||
def num2words(number, ordinal=False, lang='en'):
|
||||
|
||||
@@ -15,7 +15,11 @@
|
||||
# MA 02110-1301 USA
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import math
|
||||
|
||||
from .orderedmapping import OrderedMapping
|
||||
from .compat import to_s
|
||||
|
||||
|
||||
class Num2Word_Base(object):
|
||||
@@ -88,7 +92,7 @@ class Num2Word_Base(object):
|
||||
|
||||
def to_cardinal(self, value):
|
||||
try:
|
||||
assert long(value) == value
|
||||
assert int(value) == value
|
||||
except (ValueError, TypeError, AssertionError):
|
||||
return self.to_cardinal_float(value)
|
||||
|
||||
@@ -101,7 +105,6 @@ class Num2Word_Base(object):
|
||||
|
||||
if value >= self.MAXVAL:
|
||||
raise OverflowError(self.errmsg_toobig % (value, self.MAXVAL))
|
||||
|
||||
|
||||
val = self.splitnum(value)
|
||||
words, num = self.clean(val)
|
||||
@@ -114,9 +117,18 @@ class Num2Word_Base(object):
|
||||
except (ValueError, TypeError, AssertionError):
|
||||
raise TypeError(self.errmsg_nonnum % value)
|
||||
|
||||
value = float(value)
|
||||
pre = int(value)
|
||||
post = str(abs(value - pre) * 10**self.precision)
|
||||
post = '0' * (self.precision - len(post.split('.')[0])) + post
|
||||
post = abs(value - pre) * 10**self.precision
|
||||
if abs(round(post) - post) < 0.01:
|
||||
# We generally floor all values beyond our precision (rather than rounding), but in
|
||||
# cases where we have something like 1.239999999, which is probably due to python's
|
||||
# handling of floats, we actually want to consider it as 1.24 instead of 1.23
|
||||
post = int(round(post))
|
||||
else:
|
||||
post = int(math.floor(post))
|
||||
post = str(post)
|
||||
post = '0' * (self.precision - len(post)) + post
|
||||
|
||||
out = [self.to_cardinal(pre)]
|
||||
if self.precision:
|
||||
@@ -124,7 +136,7 @@ class Num2Word_Base(object):
|
||||
|
||||
for i in range(self.precision):
|
||||
curr = int(post[i])
|
||||
out.append(unicode(self.to_cardinal(curr)))
|
||||
out.append(to_s(self.to_cardinal(curr)))
|
||||
|
||||
return " ".join(out)
|
||||
|
||||
@@ -169,10 +181,10 @@ class Num2Word_Base(object):
|
||||
|
||||
|
||||
def verify_ordinal(self, value):
|
||||
if not value == long(value):
|
||||
raise TypeError, self.errmsg_floatord %(value)
|
||||
if not value == int(value):
|
||||
raise TypeError(self.errmsg_floatord % value)
|
||||
if not abs(value) == value:
|
||||
raise TypeError, self.errmsg_negord %(value)
|
||||
raise TypeError(self.errmsg_negord % value)
|
||||
|
||||
|
||||
def verify_num(self, value):
|
||||
@@ -182,7 +194,7 @@ class Num2Word_Base(object):
|
||||
def set_wordnums(self):
|
||||
pass
|
||||
|
||||
|
||||
|
||||
def to_ordinal(self, value):
|
||||
return self.to_cardinal(value)
|
||||
|
||||
|
||||
26
num2words/compat.py
Normal file
26
num2words/compat.py
Normal file
@@ -0,0 +1,26 @@
|
||||
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
|
||||
# Copyright (c) 2016, Savoir-faire Linux inc. All Rights Reserved.
|
||||
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2.1 of the License, or (at your option) any later version.
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301 USA
|
||||
|
||||
import sys
|
||||
|
||||
PY3 = sys.version_info[0] == 3
|
||||
|
||||
def to_s(val):
|
||||
if PY3:
|
||||
return str(val)
|
||||
else:
|
||||
return unicode(val)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
|
||||
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
|
||||
|
||||
@@ -14,10 +15,9 @@
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301 USA
|
||||
|
||||
from __future__ import unicode_literals
|
||||
from __future__ import unicode_literals, print_function
|
||||
from .lang_EU import Num2Word_EU
|
||||
|
||||
#//TODO: Use German error messages
|
||||
class Num2Word_DE(Num2Word_EU):
|
||||
def set_high_numwords(self, high):
|
||||
max = 3 + 6*len(high)
|
||||
@@ -26,12 +26,13 @@ class Num2Word_DE(Num2Word_EU):
|
||||
self.cards[10**n] = word + "illiarde"
|
||||
self.cards[10**(n-3)] = word + "illion"
|
||||
|
||||
|
||||
def setup(self):
|
||||
self.negword = "minus "
|
||||
self.pointword = "Komma"
|
||||
self.errmsg_nonnum = "Only numbers may be converted to words."
|
||||
self.errmsg_toobig = "Number is too large to convert to words."
|
||||
self.errmsg_floatord = "Die Gleitkommazahl %s kann nicht in eine Ordnungszahl konvertiert werden." # "Cannot treat float %s as ordinal."
|
||||
self.errmsg_nonnum = "Nur Zahlen (type(%s)) können in Wörter konvertiert werden." # "type(((type(%s)) ) not in [long, int, float]"
|
||||
self.errmsg_negord = "Die negative Zahl %s kann nicht in eine Ordnungszahl konvertiert werden." # "Cannot treat negative num %s as ordinal."
|
||||
self.errmsg_toobig = "Die Zahl %s muss kleiner als %s sein." # "abs(%s) must be less than %s."
|
||||
self.exclude_title = []
|
||||
|
||||
lows = ["non", "okt", "sept", "sext", "quint", "quadr", "tr", "b", "m"]
|
||||
@@ -49,61 +50,59 @@ class Num2Word_DE(Num2Word_EU):
|
||||
"zw\xF6lf", "elf", "zehn", "neun", "acht", "sieben",
|
||||
"sechs", "f\xFCnf", "vier", "drei", "zwei", "eins",
|
||||
"null"]
|
||||
self.ords = { "eins" : "ers",
|
||||
"drei" : "drit",
|
||||
"acht" : "ach",
|
||||
"sieben" : "sieb",
|
||||
"ig" : "igs" }
|
||||
self.ordflag = False
|
||||
|
||||
self.ords = {"eins": "ers",
|
||||
"drei": "drit",
|
||||
"acht": "ach",
|
||||
"sieben": "sieb",
|
||||
"ig": "igs",
|
||||
"ert": "erts",
|
||||
"end": "ends",
|
||||
"ion": "ions",
|
||||
"nen": "nens",
|
||||
"rde": "rdes",
|
||||
"rden": "rdens"}
|
||||
|
||||
def merge(self, curr, next):
|
||||
ctext, cnum, ntext, nnum = curr + next
|
||||
|
||||
if cnum == 1:
|
||||
if nnum < 10**6 or self.ordflag:
|
||||
if nnum < 10**6:
|
||||
return next
|
||||
ctext = "eine"
|
||||
|
||||
if nnum > cnum:
|
||||
if nnum >= 10**6:
|
||||
if cnum > 1:
|
||||
if ntext.endswith("e") or self.ordflag:
|
||||
ntext += "s"
|
||||
if ntext.endswith("e"):
|
||||
ntext += "n"
|
||||
else:
|
||||
ntext += "es"
|
||||
ntext += "en"
|
||||
ctext += " "
|
||||
val = cnum * nnum
|
||||
else:
|
||||
if nnum < 10 < cnum < 100:
|
||||
if nnum == 1:
|
||||
ntext = "ein"
|
||||
ntext, ctext = ctext, ntext + "und"
|
||||
ntext, ctext = ctext, ntext + "und"
|
||||
elif cnum >= 10**6:
|
||||
ctext += " "
|
||||
val = cnum + nnum
|
||||
|
||||
word = ctext + ntext
|
||||
return (word, val)
|
||||
|
||||
|
||||
def to_ordinal(self, value):
|
||||
self.verify_ordinal(value)
|
||||
self.ordflag = True
|
||||
outword = self.to_cardinal(value)
|
||||
self.ordflag = False
|
||||
for key in self.ords:
|
||||
if outword.endswith(key):
|
||||
outword = outword[:len(outword) - len(key)] + self.ords[key]
|
||||
break
|
||||
return outword + "te"
|
||||
|
||||
|
||||
# Is this correct??
|
||||
def to_ordinal_num(self, value):
|
||||
self.verify_ordinal(value)
|
||||
return str(value) + "te"
|
||||
|
||||
return str(value) + "."
|
||||
|
||||
def to_currency(self, val, longval=True, old=False):
|
||||
if old:
|
||||
@@ -117,8 +116,6 @@ class Num2Word_DE(Num2Word_EU):
|
||||
return self.to_cardinal(val)
|
||||
return self.to_splitnum(val, hightxt="hundert", longval=longval)
|
||||
|
||||
|
||||
|
||||
n2w = Num2Word_DE()
|
||||
to_card = n2w.to_cardinal
|
||||
to_ord = n2w.to_ordinal
|
||||
@@ -126,15 +123,20 @@ to_ordnum = n2w.to_ordinal_num
|
||||
|
||||
|
||||
def main():
|
||||
for val in [ 1, 11, 12, 21, 31, 33, 71, 80, 81, 91, 99, 100, 101, 102, 155,
|
||||
for val in [1, 7, 8, 12, 17, 81, 91, 99, 100, 101, 102, 155,
|
||||
180, 300, 308, 832, 1000, 1001, 1061, 1100, 1500, 1701, 3000,
|
||||
8280, 8291, 150000, 500000, 1000000, 2000000, 2000001,
|
||||
8280, 8291, 150000, 500000, 3000000, 1000000, 2000001, 1000000000, 2000000000,
|
||||
-21212121211221211111, -2.121212, -1.0000100]:
|
||||
n2w.test(val)
|
||||
|
||||
n2w.test(1325325436067876801768700107601001012212132143210473207540327057320957032975032975093275093275093270957329057320975093272950730)
|
||||
print n2w.to_currency(112121)
|
||||
print n2w.to_year(2000)
|
||||
# n2w.test(1325325436067876801768700107601001012212132143210473207540327057320957032975032975093275093275093270957329057320975093272950730)
|
||||
n2w.test(3000000)
|
||||
n2w.test(3000000000001)
|
||||
n2w.test(3000000324566)
|
||||
print(n2w.to_currency(112121))
|
||||
print(n2w.to_year(2000))
|
||||
print(n2w.to_year(1820))
|
||||
print(n2w.to_year(2001))
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301 USA
|
||||
|
||||
from __future__ import division, unicode_literals
|
||||
from __future__ import division, unicode_literals, print_function
|
||||
from num2words import lang_EU
|
||||
|
||||
class Num2Word_DK(lang_EU.Num2Word_EU):
|
||||
@@ -146,8 +146,8 @@ def main():
|
||||
n2w.test(val)
|
||||
n2w.test(1325325436067876801768700107601001012212132143210473207540327057320957032975032975093275093275093270957329057320975093272950730)
|
||||
for val in [1,120, 160, 1000,1120,1800, 1976,2000,2010,2099,2171]:
|
||||
print val, "er", n2w.to_currency(val)
|
||||
print val, "er", n2w.to_year(val)
|
||||
print(val, "er", n2w.to_currency(val))
|
||||
print(val, "er", n2w.to_year(val))
|
||||
n2w.test(65132)
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301 USA
|
||||
|
||||
from __future__ import division, unicode_literals
|
||||
from __future__ import division, unicode_literals, print_function
|
||||
from . import lang_EU
|
||||
|
||||
class Num2Word_EN(lang_EU.Num2Word_EU):
|
||||
@@ -47,7 +47,9 @@ class Num2Word_EN(lang_EU.Num2Word_EU):
|
||||
"twelve" : "twelfth" }
|
||||
|
||||
|
||||
def merge(self, (ltext, lnum), (rtext, rnum)):
|
||||
def merge(self, lpair, rpair):
|
||||
ltext, lnum = lpair
|
||||
rtext, rnum = rpair
|
||||
if lnum == 1 and rnum < 100:
|
||||
return (rtext, rnum)
|
||||
elif 100 > lnum > rnum :
|
||||
@@ -68,9 +70,9 @@ class Num2Word_EN(lang_EU.Num2Word_EU):
|
||||
lastword = self.ords[lastword]
|
||||
except KeyError:
|
||||
if lastword[-1] == "y":
|
||||
lastword = lastword[:-1] + "ie"
|
||||
lastword = lastword[:-1] + "ie"
|
||||
lastword += "th"
|
||||
lastwords[-1] = self.title(lastword)
|
||||
lastwords[-1] = self.title(lastword)
|
||||
outwords[-1] = "-".join(lastwords)
|
||||
return " ".join(outwords)
|
||||
|
||||
@@ -105,9 +107,9 @@ def main():
|
||||
n2w.test(val)
|
||||
n2w.test(1325325436067876801768700107601001012212132143210473207540327057320957032975032975093275093275093270957329057320975093272950730)
|
||||
for val in [1,120,1000,1120,1800, 1976,2000,2010,2099,2171]:
|
||||
print val, "is", n2w.to_currency(val)
|
||||
print val, "is", n2w.to_year(val)
|
||||
|
||||
print(val, "is", n2w.to_currency(val))
|
||||
print(val, "is", n2w.to_year(val))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
@@ -14,10 +14,10 @@
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301 USA
|
||||
|
||||
from __future__ import unicode_literals
|
||||
from __future__ import unicode_literals, print_function
|
||||
from .lang_EN import Num2Word_EN
|
||||
|
||||
|
||||
|
||||
class Num2Word_EN_GB(Num2Word_EN):
|
||||
def to_currency(self, val, longval=True):
|
||||
return self.to_splitnum(val, hightxt="pound/s", lowtxt="pence",
|
||||
@@ -38,9 +38,9 @@ def main():
|
||||
n2w.test(val)
|
||||
n2w.test(1325325436067876801768700107601001012212132143210473207540327057320957032975032975093275093275093270957329057320975093272950730)
|
||||
for val in [1,120,1000,1120,1800, 1976,2000,2010,2099,2171]:
|
||||
print val, "is", n2w.to_currency(val)
|
||||
print val, "is", n2w.to_year(val)
|
||||
|
||||
print(val, "is", n2w.to_currency(val))
|
||||
print(val, "is", n2w.to_year(val))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301 USA
|
||||
|
||||
from __future__ import unicode_literals
|
||||
from __future__ import unicode_literals, print_function
|
||||
from .lang_EU import Num2Word_EU
|
||||
|
||||
class Num2Word_ES(Num2Word_EU):
|
||||
@@ -173,9 +173,9 @@ def main():
|
||||
n2w.test(val)
|
||||
|
||||
n2w.test(1325325436067876801768700107601001012212132143210473207540327057320957032975032975093275093275093270957329057320975093272950730)
|
||||
print n2w.to_currency(1222)
|
||||
print n2w.to_currency(1222, old=True)
|
||||
print n2w.to_year(1222)
|
||||
print(n2w.to_currency(1222))
|
||||
print(n2w.to_currency(1222, old=True))
|
||||
print(n2w.to_year(1222))
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301 USA
|
||||
|
||||
from __future__ import unicode_literals
|
||||
from __future__ import unicode_literals, print_function
|
||||
from .lang_EU import Num2Word_EU
|
||||
|
||||
|
||||
@@ -106,8 +106,8 @@ def main():
|
||||
n2w.test(val)
|
||||
|
||||
n2w.test(1325325436067876801768700107601001012212132143210473207540327057320957032975032975093275093275093270957329057320975093272950730)
|
||||
print n2w.to_currency(112121)
|
||||
print n2w.to_year(1996)
|
||||
print(n2w.to_currency(112121))
|
||||
print(n2w.to_year(1996))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301 USA
|
||||
|
||||
from __future__ import unicode_literals
|
||||
from __future__ import unicode_literals, print_function
|
||||
from .lang_EU import Num2Word_EU
|
||||
|
||||
class Num2Word_FR_CH(Num2Word_EU):
|
||||
@@ -101,8 +101,8 @@ def main():
|
||||
n2w.test(val)
|
||||
|
||||
n2w.test(1325325436067876801768700107601001012212132143210473207540327057320957032975032975093275093275093270957329057320975093272950730)
|
||||
print n2w.to_currency(112121)
|
||||
print n2w.to_year(1996)
|
||||
print(n2w.to_currency(112121))
|
||||
print(n2w.to_year(1996))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
162
num2words/lang_HE.py
Normal file
162
num2words/lang_HE.py
Normal file
@@ -0,0 +1,162 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
|
||||
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
|
||||
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2.1 of the License, or (at your option) any later version.
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301 USA
|
||||
|
||||
|
||||
from __future__ import unicode_literals, print_function
|
||||
|
||||
ZERO = (u'אפס',)
|
||||
|
||||
ONES = {
|
||||
1: (u'אחד',),
|
||||
2: (u'שנים',),
|
||||
3: (u'שלש',),
|
||||
4: (u'ארבע',),
|
||||
5: (u'חמש',),
|
||||
6: (u'שש',),
|
||||
7: (u'שבע',),
|
||||
8: (u'שמנה',),
|
||||
9: (u'תשע',),
|
||||
}
|
||||
|
||||
TENS = {
|
||||
0: (u'עשר',),
|
||||
1: (u'אחד עשרה',),
|
||||
2: (u'שנים עשרה',),
|
||||
3: (u'שלש עשרה',),
|
||||
4: (u'ארבע עשרה',),
|
||||
5: (u'חמש עשרה',),
|
||||
6: (u'שש עשרה',),
|
||||
7: (u'שבע עשרה',),
|
||||
8: (u'שמנה עשרה',),
|
||||
9: (u'תשע עשרה',),
|
||||
}
|
||||
|
||||
TWENTIES = {
|
||||
2: (u'עשרים',),
|
||||
3: (u'שלשים',),
|
||||
4: (u'ארבעים',),
|
||||
5: (u'חמישים',),
|
||||
6: (u'ששים',),
|
||||
7: (u'שבעים',),
|
||||
8: (u'שמנים',),
|
||||
9: (u'תשעים',),
|
||||
}
|
||||
|
||||
HUNDRED = {
|
||||
1: (u'מאה',),
|
||||
2: (u'מאתיים',),
|
||||
3: (u'מאות',)
|
||||
}
|
||||
|
||||
THOUSANDS = {
|
||||
1: (u'אלף',),
|
||||
2: (u'אלפיים',),
|
||||
}
|
||||
|
||||
AND = u'ו'
|
||||
|
||||
def splitby3(n):
|
||||
length = len(n)
|
||||
if length > 3:
|
||||
start = length % 3
|
||||
if start > 0:
|
||||
yield int(n[:start])
|
||||
for i in range(start, length, 3):
|
||||
yield int(n[i:i+3])
|
||||
else:
|
||||
yield int(n)
|
||||
|
||||
|
||||
def get_digits(n):
|
||||
return [int(x) for x in reversed(list(('%03d' % n)[-3:]))]
|
||||
|
||||
|
||||
def pluralize(n, forms):
|
||||
# gettext implementation:
|
||||
# (n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2)
|
||||
|
||||
form = 0 if (n % 10 == 1 and n % 100 != 11) else 1 if n != 0 else 2
|
||||
|
||||
return forms[form]
|
||||
|
||||
|
||||
def int2word(n):
|
||||
if n > 9999: #doesn't yet work for numbers this big
|
||||
raise NotImplementedError()
|
||||
|
||||
if n == 0:
|
||||
return ZERO[0]
|
||||
|
||||
words = []
|
||||
|
||||
chunks = list(splitby3(str(n)))
|
||||
i = len(chunks)
|
||||
for x in chunks:
|
||||
i -= 1
|
||||
n1, n2, n3 = get_digits(x)
|
||||
|
||||
# print str(n3) + str(n2) + str(n1)
|
||||
|
||||
if n3 > 0:
|
||||
if n3 <= 2:
|
||||
words.append(HUNDRED[n3][0])
|
||||
else:
|
||||
words.append(ONES[n3][0])
|
||||
words.append(HUNDRED[3][0])
|
||||
|
||||
if n2 > 1:
|
||||
words.append(TWENTIES[n2][0])
|
||||
|
||||
if n2 == 1:
|
||||
words.append(TENS[n1][0])
|
||||
elif n1 > 0 and not (i > 0 and x == 1):
|
||||
words.append(ONES[n1][0])
|
||||
|
||||
if i > 0:
|
||||
if i <= 2:
|
||||
words.append(THOUSANDS[i][0])
|
||||
else:
|
||||
words.append(ONES[i][0])
|
||||
words.append(THOUSANDS[1][0])
|
||||
|
||||
if len(words) > 1:
|
||||
words[-1] = AND + words[-1]
|
||||
return ' '.join(words)
|
||||
|
||||
|
||||
def n2w(n):
|
||||
return int2word(int(n))
|
||||
|
||||
|
||||
def to_currency(n, currency='EUR', cents=True, seperator=','):
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
class Num2Word_HE(object):
|
||||
def to_cardinal(self, number):
|
||||
return n2w(number)
|
||||
|
||||
def to_ordinal(self, number):
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
yo = Num2Word_HE()
|
||||
nums = [1, 11, 21, 24, 99, 100, 101, 200, 211, 345, 1000, 1011]
|
||||
for num in nums:
|
||||
print(num, yo.to_cardinal(num))
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301 USA
|
||||
|
||||
from __future__ import unicode_literals, print_function
|
||||
|
||||
class Num2Word_ID():
|
||||
|
||||
BASE = {0: [],
|
||||
@@ -188,7 +190,7 @@ class Num2Word_ID():
|
||||
return self.to_cardinal(value)
|
||||
|
||||
def verify_ordinal(self, value):
|
||||
if not value == long(value):
|
||||
raise TypeError, self.errmsg_floatord %(value)
|
||||
if not value == int(value):
|
||||
raise TypeError(self.errmsg_floatord % value)
|
||||
if not abs(value) == value:
|
||||
raise TypeError, self.errmsg_negord %(value)
|
||||
raise TypeError(self.errmsg_negord % value)
|
||||
|
||||
202
num2words/lang_IT.py
Normal file
202
num2words/lang_IT.py
Normal file
@@ -0,0 +1,202 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
#
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2.1 of the License, or (at your option) any later version.
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301 USA
|
||||
|
||||
from __future__ import unicode_literals
|
||||
from .lang_EU import Num2Word_EU
|
||||
|
||||
# Globals
|
||||
# -------
|
||||
|
||||
ZERO = "zero"
|
||||
|
||||
CARDINAL_WORDS = [
|
||||
ZERO, "uno", "due", "tre", "quattro", "cinque", "sei", "sette", "otto",
|
||||
"nove", "dieci", "undici", "dodici", "tredici", "quattordici", "quindici",
|
||||
"sedici", "diciassette", "diciotto", "diciannove"
|
||||
]
|
||||
|
||||
ORDINAL_WORDS = [
|
||||
ZERO, "primo", "secondo", "terzo", "quarto", "quinto", "sesto", "settimo",
|
||||
"ottavo", "nono", "decimo", "undicesimo", "dodicesimo", "tredicesimo",
|
||||
"quattordicesimo", "quindicesimo", "sedicesimo", "diciassettesimo",
|
||||
"diciottesimo", "diciannovesimo"
|
||||
]
|
||||
|
||||
# The script can extrapolate the missing numbers from the base forms.
|
||||
STR_TENS = {2: "venti", 3: "trenta", 4: "quaranta", 6: "sessanta"}
|
||||
|
||||
# These prefixes are used for extremely big numbers.
|
||||
EXPONENT_PREFIXES = [
|
||||
ZERO, "m", "b", "tr", "quadr", "quint", "sest", "sett", "ott", "nov", "dec"
|
||||
]
|
||||
|
||||
# Utils
|
||||
# =====
|
||||
|
||||
def phonetic_contraction(string):
|
||||
return (string
|
||||
.replace("oo", "o") # ex. "centootto"
|
||||
.replace("ao", "o") # ex. "settantaotto"
|
||||
.replace("io", "o") # ex. "ventiotto"
|
||||
.replace("au", "u") # ex. "trentauno"
|
||||
)
|
||||
|
||||
def exponent_length_to_string(exponent_length):
|
||||
# We always assume `exponent` to be a multiple of 3. If it's not true, then
|
||||
# Num2Word_IT.big_number_to_cardinal did something wrong.
|
||||
prefix = EXPONENT_PREFIXES[exponent_length // 6]
|
||||
if exponent_length % 6 == 0:
|
||||
return prefix + "ilione"
|
||||
else:
|
||||
return prefix + "iliardo"
|
||||
|
||||
def accentuate(string):
|
||||
# This is inefficient: it may do several rewritings when deleting
|
||||
# half-sentence accents. However, it is the easiest method and speed is
|
||||
# not crucial (duh), so...
|
||||
return " ".join(
|
||||
# Deletes half-sentence accents and accentuates the last "tre"
|
||||
[w.replace("tré", "tre")[:-3] + "tré"
|
||||
# We shouldn't accentuate a single "tre": is has to be a composite
|
||||
# word. ~~~~~~~~~~
|
||||
if w[-3:] == "tre" and len(w) > 3
|
||||
# Deletes half-sentence accents anyway
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~
|
||||
else w.replace("tré", "tre")
|
||||
for w in string.split()
|
||||
])
|
||||
|
||||
def omitt_if_zero(number_to_string):
|
||||
return "" if number_to_string == ZERO else number_to_string
|
||||
|
||||
# Main class
|
||||
# ==========
|
||||
|
||||
class Num2Word_IT:
|
||||
|
||||
MINUS_PREFIX_WORD = "meno "
|
||||
FLOAT_INFIX_WORD = " virgola "
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def float_to_words(self, float_number, ordinal=False):
|
||||
if ordinal:
|
||||
prefix = self.to_ordinal(int(float_number))
|
||||
else:
|
||||
prefix = self.to_cardinal(int(float_number))
|
||||
postfix = " ".join(
|
||||
# Drops the trailing zero and comma ~~~~
|
||||
[self.to_cardinal(int(c)) for c in str(float_number % 1)[2:]]
|
||||
)
|
||||
return prefix + Num2Word_IT.FLOAT_INFIX_WORD + postfix
|
||||
|
||||
def tens_to_cardinal(self, number):
|
||||
tens = number // 10
|
||||
units = number % 10
|
||||
if tens in STR_TENS:
|
||||
prefix = STR_TENS[tens]
|
||||
else:
|
||||
prefix = CARDINAL_WORDS[tens][:-1] + "anta"
|
||||
postfix = omitt_if_zero(CARDINAL_WORDS[units])
|
||||
return phonetic_contraction(prefix + postfix)
|
||||
|
||||
def hundreds_to_cardinal(self, number):
|
||||
hundreds = number // 100
|
||||
prefix = "cento"
|
||||
if hundreds != 1:
|
||||
prefix = CARDINAL_WORDS[hundreds] + prefix
|
||||
postfix = omitt_if_zero(self.to_cardinal(number % 100))
|
||||
return phonetic_contraction(prefix + postfix)
|
||||
|
||||
def thousands_to_cardinal(self, number):
|
||||
thousands = number // 1000
|
||||
if thousands == 1:
|
||||
prefix = "mille"
|
||||
else:
|
||||
prefix = self.to_cardinal(thousands) + "mila"
|
||||
postfix = omitt_if_zero(self.to_cardinal(number % 1000))
|
||||
# "mille" and "mila" don't need any phonetic contractions
|
||||
return prefix + postfix
|
||||
|
||||
def big_number_to_cardinal(self, number):
|
||||
digits = [c for c in str(number)]
|
||||
length = len(digits)
|
||||
if length >= 66:
|
||||
raise NotImplementedError("The given number is too large.")
|
||||
# This is how many digits come before the "illion" term.
|
||||
# cento miliardi => 3
|
||||
# dieci milioni => 2
|
||||
# un miliardo => 1
|
||||
predigits = length % 3 or 3
|
||||
multiplier = digits[:predigits]
|
||||
exponent = digits[predigits:]
|
||||
# Default infix string: "milione", "biliardo", "sestilione", ecc.
|
||||
infix = exponent_length_to_string(len(exponent))
|
||||
if multiplier == ["1"]:
|
||||
prefix = "un "
|
||||
else:
|
||||
prefix = self.to_cardinal(int("".join(multiplier)))
|
||||
# Plural form ~~~~~~~~~~~
|
||||
infix = " " + infix[:-1] + "i"
|
||||
# Read as: Does the value of exponent equal 0?
|
||||
if set(exponent) != set("0"):
|
||||
postfix = self.to_cardinal(int("".join(exponent)))
|
||||
if " e " in postfix:
|
||||
infix += ", "
|
||||
else:
|
||||
infix += " e "
|
||||
else:
|
||||
postfix = ""
|
||||
return prefix + infix + postfix
|
||||
|
||||
def to_cardinal(self, number):
|
||||
if number < 0:
|
||||
string = Num2Word_IT.MINUS_PREFIX_WORD + self.to_cardinal(-number)
|
||||
elif number % 1 != 0:
|
||||
string = self.float_to_words(number)
|
||||
elif number < 20:
|
||||
string = CARDINAL_WORDS[number]
|
||||
elif number < 100:
|
||||
string = self.tens_to_cardinal(number)
|
||||
elif number < 1000:
|
||||
string = self.hundreds_to_cardinal(number)
|
||||
elif number < 1000000:
|
||||
string = self.thousands_to_cardinal(number)
|
||||
else:
|
||||
string = self.big_number_to_cardinal(number)
|
||||
return accentuate(string)
|
||||
|
||||
def to_ordinal(self, number):
|
||||
tens = number % 100
|
||||
# Italian grammar is poorly defined here ¯\_(ツ)_/¯:
|
||||
# centodecimo VS centodieciesimo VS centesimo decimo?
|
||||
is_outside_teens = not 10 < tens < 20
|
||||
if number < 0:
|
||||
return Num2Word_IT.MINUS_PREFIX_WORD + self.to_ordinal(-number)
|
||||
elif number % 1 != 0:
|
||||
return self.float_to_words(number, ordinal=True)
|
||||
elif number < 20:
|
||||
return ORDINAL_WORDS[number]
|
||||
elif is_outside_teens and tens % 10 == 3:
|
||||
# Gets ride of the accent ~~~~~~~~~~
|
||||
return self.to_cardinal(number)[:-1] + "eesimo"
|
||||
elif is_outside_teens and tens % 10 == 6:
|
||||
return self.to_cardinal(number) + "esimo"
|
||||
else:
|
||||
string = self.to_cardinal(number)[:-1]
|
||||
if string[-3:] == "mil":
|
||||
string += "l"
|
||||
return string + "esimo"
|
||||
@@ -85,7 +85,13 @@ vienas litas, nulis centų
|
||||
vienas tūkstantis du šimtai trisdešimt keturi litai, penkiasdešimt šeši centai
|
||||
|
||||
>>> print(to_currency(-1251985, cents = False))
|
||||
minus dvylika tūkstančių penki šimtai devyniolika litų, 85 centai
|
||||
minus dvylika tūkstančių penki šimtai devyniolika eurų, 85 centai
|
||||
|
||||
>>> print(to_currency(1.0, 'EUR'))
|
||||
vienas euras, nulis centų
|
||||
|
||||
>>> print(to_currency(1234.56, 'EUR'))
|
||||
vienas tūkstantis du šimtai trisdešimt keturi eurai, penkiasdešimt šeši centai
|
||||
"""
|
||||
from __future__ import unicode_literals
|
||||
|
||||
@@ -144,6 +150,7 @@ THOUSANDS = {
|
||||
|
||||
CURRENCIES = {
|
||||
'LTL': ((u'litas', u'litai', u'litų'), (u'centas', u'centai', u'centų')),
|
||||
'EUR': ((u'euras', u'eurai', u'eurų'), (u'centas', u'centai', u'centų')),
|
||||
}
|
||||
|
||||
def splitby3(n):
|
||||
@@ -210,7 +217,7 @@ def n2w(n):
|
||||
else:
|
||||
return int2word(int(n))
|
||||
|
||||
def to_currency(n, currency='LTL', cents = True):
|
||||
def to_currency(n, currency='EUR', cents = True):
|
||||
if type(n) == int:
|
||||
if n < 0:
|
||||
minus = True
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301 USA
|
||||
|
||||
from __future__ import division, unicode_literals
|
||||
from __future__ import division, unicode_literals, print_function
|
||||
from . import lang_EU
|
||||
|
||||
class Num2Word_NO(lang_EU.Num2Word_EU):
|
||||
@@ -54,7 +54,9 @@ class Num2Word_NO(lang_EU.Num2Word_EU):
|
||||
"tjue" : "tjuende" }
|
||||
|
||||
|
||||
def merge(self, (ltext, lnum), (rtext, rnum)):
|
||||
def merge(self, lpair, rpair):
|
||||
ltext, lnum = lpair
|
||||
rtext, rnum = rpair
|
||||
if lnum == 1 and rnum < 100:
|
||||
return (rtext, rnum)
|
||||
elif 100 > lnum > rnum :
|
||||
@@ -75,10 +77,10 @@ class Num2Word_NO(lang_EU.Num2Word_EU):
|
||||
lastword = self.ords[lastword]
|
||||
except KeyError:
|
||||
if lastword[-2:] == "ti":
|
||||
lastword = lastword + "ende"
|
||||
lastword = lastword + "ende"
|
||||
else:
|
||||
lastword += "de"
|
||||
lastwords[-1] = self.title(lastword)
|
||||
lastwords[-1] = self.title(lastword)
|
||||
outwords[-1] = "".join(lastwords)
|
||||
return " ".join(outwords)
|
||||
|
||||
@@ -113,9 +115,9 @@ def main():
|
||||
n2w.test(val)
|
||||
n2w.test(1325325436067876801768700107601001012212132143210473207540327057320957032975032975093275093275093270957329057320975093272950730)
|
||||
for val in [1,120,1000,1120,1800, 1976,2000,2010,2099,2171]:
|
||||
print val, "er", n2w.to_currency(val)
|
||||
print val, "er", n2w.to_year(val)
|
||||
|
||||
print(val, "er", n2w.to_currency(val))
|
||||
print(val, "er", n2w.to_year(val))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
@@ -55,6 +55,9 @@ dwa tysiące dwanaście
|
||||
>>> print(n2w(12519.85))
|
||||
dwanaście tysięcy pięćset dziewiętnaście przecinek osiemdziesiąt pięć
|
||||
|
||||
>>> print(n2w(123.50))
|
||||
sto dwadzieścia trzy przecinek pięć
|
||||
|
||||
>>> print(fill(n2w(1234567890)))
|
||||
miliard dwieście trzydzieści cztery miliony pięćset sześćdziesiąt
|
||||
siedem tysięcy osiemset dziewięćdzisiąt
|
||||
@@ -95,6 +98,9 @@ sto jeden złotych i dwadzieścia jeden groszy
|
||||
|
||||
>>> print(to_currency(-1251985, cents = False))
|
||||
minus dwanaście tysięcy pięćset dziewiętnaście euro, 85 centów
|
||||
|
||||
>>> print(to_currency(123.50, 'PLN', seperator=' i'))
|
||||
sto dwadzieścia trzy złote i pięćdziesiąt groszy
|
||||
"""
|
||||
from __future__ import unicode_literals
|
||||
|
||||
@@ -178,7 +184,7 @@ def splitby3(n):
|
||||
if start > 0:
|
||||
yield int(n[:start])
|
||||
for i in range(start, length, 3):
|
||||
yield int(n[i:i+3])
|
||||
yield int(n[i:i + 3])
|
||||
else:
|
||||
yield int(n)
|
||||
|
||||
@@ -188,7 +194,7 @@ def get_digits(n):
|
||||
|
||||
|
||||
def pluralize(n, forms):
|
||||
form = 0 if n==1 else 1 if (n % 10 > 1 and n % 10 < 5 and (n % 100 < 10 or n % 100 > 20)) else 2
|
||||
form = 0 if n == 1 else 1 if (n % 10 > 1 and n % 10 < 5 and (n % 100 < 10 or n % 100 > 20)) else 2
|
||||
return forms[form]
|
||||
|
||||
|
||||
@@ -203,11 +209,9 @@ def int2word(n):
|
||||
i -= 1
|
||||
n1, n2, n3 = get_digits(x)
|
||||
|
||||
# print str(n3) + str(n2) + str(n1)
|
||||
|
||||
if n3 > 0:
|
||||
words.append(HUNDREDS[n3][0])
|
||||
|
||||
|
||||
if n2 > 1:
|
||||
words.append(TWENTIES[n2][0])
|
||||
|
||||
@@ -231,7 +235,7 @@ def n2w(n):
|
||||
return int2word(int(n))
|
||||
|
||||
|
||||
def to_currency(n, currency='EUR', cents=True, seperator=','):
|
||||
def to_currency(n, currency = 'EUR', cents = True, seperator = ','):
|
||||
if type(n) == int:
|
||||
if n < 0:
|
||||
minus = True
|
||||
@@ -239,12 +243,14 @@ def to_currency(n, currency='EUR', cents=True, seperator=','):
|
||||
minus = False
|
||||
|
||||
n = abs(n)
|
||||
left = n / 100
|
||||
left = n // 100
|
||||
right = n % 100
|
||||
else:
|
||||
n = str(n).replace(',', '.')
|
||||
if '.' in n:
|
||||
left, right = n.split('.')
|
||||
if len(right) == 1:
|
||||
right = right + '0'
|
||||
else:
|
||||
left, right = n, 0
|
||||
left, right = int(left), int(right)
|
||||
|
||||
@@ -30,9 +30,9 @@ class Num2Word_PT_BR(lang_EU.Num2Word_EU):
|
||||
|
||||
def setup(self):
|
||||
self.negword = "menos "
|
||||
self.pointword = "ponto"
|
||||
self.pointword = "vírgula"
|
||||
self.errmsg_nornum = "Somente números podem ser convertidos para palavras"
|
||||
self.exclude_title = ["e", "ponto", "menos"]
|
||||
self.exclude_title = ["e", "vírgula", "menos"]
|
||||
|
||||
self.mid_numwords = [
|
||||
(1000, "mil"), (100, "cem"), (90, "noventa"),
|
||||
|
||||
102
num2words/lang_VN.py
Normal file
102
num2words/lang_VN.py
Normal file
@@ -0,0 +1,102 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
|
||||
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
|
||||
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2.1 of the License, or (at your option) any later version.
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301 USA
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
|
||||
to_19 = (u'không', u'một', u'hai', u'ba', u'bốn', u'năm', u'sáu',
|
||||
u'bảy', u'tám', u'chín', u'mười', u'mười một', u'mười hai',
|
||||
u'mười ba', u'mười bốn', u'mười lăm', u'mười sáu', u'mười bảy',
|
||||
u'mười tám', u'mười chín')
|
||||
tens = (u'hai mươi', u'ba mươi', u'bốn mươi', u'năm mươi',
|
||||
u'sáu mươi', u'bảy mươi', u'tám mươi', u'chín mươi')
|
||||
denom = ('',
|
||||
u'nghìn', u'triệu', u'tỷ', u'nghìn tỷ', u'trăm nghìn tỷ',
|
||||
'Quintillion', 'Sextillion', 'Septillion', 'Octillion', 'Nonillion',
|
||||
'Decillion', 'Undecillion', 'Duodecillion', 'Tredecillion',
|
||||
'Quattuordecillion', 'Sexdecillion', 'Septendecillion',
|
||||
'Octodecillion', 'Novemdecillion', 'Vigintillion')
|
||||
|
||||
|
||||
class Num2Word_VN(object):
|
||||
|
||||
def _convert_nn(self, val):
|
||||
if val < 20:
|
||||
return to_19[val]
|
||||
for (dcap, dval) in ((k, 20 + (10 * v)) for (v, k) in enumerate(tens)):
|
||||
if dval + 10 > val:
|
||||
if val % 10:
|
||||
a = u'lăm'
|
||||
if to_19[val % 10] == u'một':
|
||||
a = u'mốt'
|
||||
else:
|
||||
a = to_19[val % 10]
|
||||
if to_19[val % 10] == u'năm':
|
||||
a = u'lăm'
|
||||
return dcap + ' ' + a
|
||||
return dcap
|
||||
|
||||
def _convert_nnn(self, val):
|
||||
word = ''
|
||||
(mod, rem) = (val % 100, val // 100)
|
||||
if rem > 0:
|
||||
word = to_19[rem] + u' trăm'
|
||||
if mod > 0:
|
||||
word = word + ' '
|
||||
if mod > 0 and mod < 10:
|
||||
if mod == 5:
|
||||
word = word != '' and word + u'lẻ năm' or word + u'năm'
|
||||
else:
|
||||
word = word != '' and word + u'lẻ ' \
|
||||
+ self._convert_nn(mod) or word + self._convert_nn(mod)
|
||||
if mod >= 10:
|
||||
word = word + self._convert_nn(mod)
|
||||
return word
|
||||
|
||||
def vietnam_number(self, val):
|
||||
if val < 100:
|
||||
return self._convert_nn(val)
|
||||
if val < 1000:
|
||||
return self._convert_nnn(val)
|
||||
for (didx, dval) in ((v - 1, 1000 ** v) for v in range(len(denom))):
|
||||
if dval > val:
|
||||
mod = 1000 ** didx
|
||||
l = val // mod
|
||||
r = val - (l * mod)
|
||||
|
||||
ret = self._convert_nnn(l) + u' ' + denom[didx]
|
||||
if r > 0 and r <= 99:
|
||||
ret = self._convert_nnn(l) + u' ' + denom[didx] + u' lẻ'
|
||||
if r > 0:
|
||||
ret = ret + ' ' + self.vietnam_number(r)
|
||||
return ret
|
||||
|
||||
def number_to_text(self, number):
|
||||
number = '%.2f' % number
|
||||
the_list = str(number).split('.')
|
||||
start_word = self.vietnam_number(int(the_list[0]))
|
||||
final_result = start_word
|
||||
if len(the_list) > 1 and int(the_list[1]) > 0:
|
||||
end_word = self.vietnam_number(int(the_list[1]))
|
||||
final_result = final_result + ' phẩy ' + end_word
|
||||
return final_result
|
||||
|
||||
def to_cardinal(self, number):
|
||||
return self.number_to_text(number)
|
||||
|
||||
def to_ordinal(self, number):
|
||||
return self.to_cardinal(number)
|
||||
Reference in New Issue
Block a user