mirror of
https://github.com/bblaz/num2words.git
synced 2025-12-06 06:42:25 +00:00
Added setup.py and restructured module
This commit is contained in:
60
pynum2word/num2word.py
Normal file
60
pynum2word/num2word.py
Normal file
@@ -0,0 +1,60 @@
|
||||
'''
|
||||
Module: num2word.py
|
||||
Requires: num2word_*.py
|
||||
Version: 0.2
|
||||
|
||||
Author:
|
||||
Taro Ogawa (tso@users.sourceforge.org)
|
||||
|
||||
Copyright:
|
||||
Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
|
||||
|
||||
Licence:
|
||||
This module is distributed under the Lesser General Public Licence.
|
||||
http://www.opensource.org/licenses/lgpl-license.php
|
||||
|
||||
Usage:
|
||||
from num2word import to_card, to_ord, to_ordnum
|
||||
to_card(1234567890)
|
||||
to_ord(1234567890)
|
||||
to_ordnum(12)
|
||||
|
||||
Notes:
|
||||
The module is a wrapper for language-specific modules. It imports the
|
||||
appropriate modules as defined by locale settings. If unable to
|
||||
load an appropriate module, an ImportError is raised.
|
||||
|
||||
History:
|
||||
0.2: n2w, to_card, to_ord, to_ordnum now imported correctly
|
||||
'''
|
||||
import locale as _locale
|
||||
|
||||
# Correct omissions in locale:
|
||||
# Bugrep these...
|
||||
_locdict = { "English_Australia" : "en_AU", }
|
||||
|
||||
|
||||
_modules = []
|
||||
for _loc in [_locale.getlocale(), _locale.getdefaultlocale()]:
|
||||
_lang = _loc[0]
|
||||
if _lang:
|
||||
_lang = _locdict.get(_lang, _lang)
|
||||
_lang = _lang.upper()
|
||||
|
||||
_modules.append("num2word_" + _lang)
|
||||
_modules.append("num2word_" + _lang.split("_")[0])
|
||||
|
||||
for _module in _modules:
|
||||
try:
|
||||
n2wmod = __import__(_module)
|
||||
break
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
try:
|
||||
n2w, to_card, to_ord, to_ordnum, to_year = (n2wmod.n2w, n2wmod.to_card,
|
||||
n2wmod.to_ord, n2wmod.to_ordnum,
|
||||
n2wmod.to_year)
|
||||
except NameError:
|
||||
raise ImportError("Could not import any of these modules: %s"
|
||||
% (", ".join(_modules)))
|
||||
154
pynum2word/num2word_DE.py
Normal file
154
pynum2word/num2word_DE.py
Normal file
@@ -0,0 +1,154 @@
|
||||
'''
|
||||
Module: num2word_DE.py
|
||||
Requires: num2word_base.py
|
||||
Version: 0.4
|
||||
|
||||
Author:
|
||||
Taro Ogawa (tso@users.sourceforge.org)
|
||||
|
||||
Copyright:
|
||||
Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
|
||||
|
||||
Licence:
|
||||
This module is distributed under the Lesser General Public Licence.
|
||||
http://www.opensource.org/licenses/lgpl-license.php
|
||||
|
||||
Data from:
|
||||
- http://german4u2know.tripod.com/nouns/10.html
|
||||
- http://www.uni-bonn.de/~manfear/large.php
|
||||
|
||||
Usage:
|
||||
from num2word_DE import to_card, to_ord, to_ordnum
|
||||
to_card(1234567890)
|
||||
to_ord(1234567890)
|
||||
to_ordnum(12)
|
||||
|
||||
History
|
||||
0.4: Use high ascii characters instead of low ascii approximations
|
||||
add to_currency() and to_year()
|
||||
|
||||
'''
|
||||
from num2word_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)
|
||||
|
||||
for word, n in zip(high, range(max, 3, -6)):
|
||||
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.exclude_title = []
|
||||
|
||||
lows = ["non", "okt", "sept", "sext", "quint", "quadr", "tr", "b", "m"]
|
||||
units = ["", "un", "duo", "tre", "quattuor", "quin", "sex", "sept",
|
||||
"okto", "novem"]
|
||||
tens = ["dez", "vigint", "trigint", "quadragint", "quinquagint",
|
||||
"sexagint", "septuagint", "oktogint", "nonagint"]
|
||||
self.high_numwords = ["zent"]+self.gen_high_numwords(units, tens, lows)
|
||||
self.mid_numwords = [(1000, "tausand"), (100, "hundert"),
|
||||
(90, "neunzig"), (80, "achtzig"), (70, "siebzig"),
|
||||
(60, "sechzig"), (50, "f\xFCnfzig"), (40, "vierzig"),
|
||||
(30, "drei\xDFig")]
|
||||
self.low_numwords = ["zwanzig", "neunzehn", "achtzen", "siebzehn",
|
||||
"sechzehn", "f\xFCnfzehn", "vierzehn", "dreizehn",
|
||||
"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
|
||||
|
||||
|
||||
def merge(self, curr, next):
|
||||
ctext, cnum, ntext, nnum = curr + next
|
||||
|
||||
if cnum == 1:
|
||||
if nnum < 10**6 or self.ordflag:
|
||||
return next
|
||||
ctext = "eine"
|
||||
|
||||
if nnum > cnum:
|
||||
if nnum >= 10**6:
|
||||
if cnum > 1:
|
||||
if ntext.endswith("e") or self.ordflag:
|
||||
ntext += "s"
|
||||
else:
|
||||
ntext += "es"
|
||||
ctext += " "
|
||||
val = cnum * nnum
|
||||
else:
|
||||
if nnum < 10 < cnum < 100:
|
||||
if nnum == 1:
|
||||
ntext = "ein"
|
||||
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"
|
||||
|
||||
|
||||
def to_currency(self, val, longval=True, old=False):
|
||||
if old:
|
||||
return self.to_splitnum(val, hightxt="mark/s", lowtxt="pfennig/e",
|
||||
jointxt="und",longval=longval)
|
||||
return super(Num2Word_DE, self).to_currency(val, jointxt="und",
|
||||
longval=longval)
|
||||
|
||||
def to_year(self, val, longval=True):
|
||||
if not (val//100)%10:
|
||||
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
|
||||
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,
|
||||
180, 300, 308, 832, 1000, 1001, 1061, 1100, 1500, 1701, 3000,
|
||||
8280, 8291, 150000, 500000, 1000000, 2000000, 2000001,
|
||||
-21212121211221211111, -2.121212, -1.0000100]:
|
||||
n2w.test(val)
|
||||
|
||||
n2w.test(1325325436067876801768700107601001012212132143210473207540327057320957032975032975093275093275093270957329057320975093272950730)
|
||||
print n2w.to_currency(112121)
|
||||
print n2w.to_year(2000)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
135
pynum2word/num2word_EN.py
Normal file
135
pynum2word/num2word_EN.py
Normal file
@@ -0,0 +1,135 @@
|
||||
'''
|
||||
Module: num2word_EN.py
|
||||
Requires: num2word_EU.py
|
||||
Version: 1.2
|
||||
|
||||
Author:
|
||||
Taro Ogawa (tso@users.sourceforge.org)
|
||||
|
||||
Copyright:
|
||||
Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
|
||||
|
||||
Licence:
|
||||
This module is distributed under the Lesser General Public Licence.
|
||||
http://www.opensource.org/licenses/lgpl-license.php
|
||||
|
||||
Data from:
|
||||
http://www.uni-bonn.de/~manfear/large.php
|
||||
|
||||
Usage:
|
||||
from num2word_EN import n2w, to_card, to_ord, to_ordnum
|
||||
to_card(1234567890)
|
||||
n2w.is_title = True
|
||||
to_card(1234567890)
|
||||
to_ord(1234567890)
|
||||
to_ordnum(1234567890)
|
||||
to_year(1976)
|
||||
to_currency(dollars*100 + cents, longval=False)
|
||||
to_currency((dollars, cents))
|
||||
|
||||
|
||||
History:
|
||||
1.2: to_ordinal_num() made shorter and simpler (but slower)
|
||||
strings in merge() now interpolated
|
||||
to_year() and to_currency() added
|
||||
|
||||
1.1: to_ordinal_num() fixed for 11,12,13
|
||||
'''
|
||||
from __future__ import division
|
||||
import num2word_EU
|
||||
|
||||
|
||||
class Num2Word_EN(num2word_EU.Num2Word_EU):
|
||||
def set_high_numwords(self, high):
|
||||
max = 3 + 3*len(high)
|
||||
for word, n in zip(high, range(max, 3, -3)):
|
||||
self.cards[10**n] = word + "illion"
|
||||
|
||||
def setup(self):
|
||||
self.negword = "minus "
|
||||
self.pointword = "point"
|
||||
self.errmsg_nornum = "Only numbers may be converted to words."
|
||||
self.exclude_title = ["and", "point", "minus"]
|
||||
|
||||
self.mid_numwords = [(1000, "thousand"), (100, "hundred"),
|
||||
(90, "ninety"), (80, "eighty"), (70, "seventy"),
|
||||
(60, "sixty"), (50, "fifty"), (40, "forty"),
|
||||
(30, "thirty")]
|
||||
self.low_numwords = ["twenty", "nineteen", "eighteen", "seventeen",
|
||||
"sixteen", "fifteen", "fourteen", "thirteen",
|
||||
"twelve", "eleven", "ten", "nine", "eight",
|
||||
"seven", "six", "five", "four", "three", "two",
|
||||
"one", "zero"]
|
||||
self.ords = { "one" : "first",
|
||||
"two" : "second",
|
||||
"three" : "third",
|
||||
"five" : "fifth",
|
||||
"eight" : "eighth",
|
||||
"nine" : "ninth",
|
||||
"twelve" : "twelfth" }
|
||||
|
||||
|
||||
def merge(self, (ltext, lnum), (rtext, rnum)):
|
||||
if lnum == 1 and rnum < 100:
|
||||
return (rtext, rnum + lnum)
|
||||
elif 100 > lnum > rnum :
|
||||
return ("%s-%s"%(ltext, rtext), lnum + rnum)
|
||||
elif lnum >= 100 > rnum:
|
||||
return ("%s and %s"%(ltext, rtext), lnum + rnum)
|
||||
elif rnum > lnum:
|
||||
return ("%s %s"%(ltext, rtext), lnum * rnum)
|
||||
return ("%s, %s"%(ltext, rtext), lnum + rnum)
|
||||
|
||||
|
||||
def to_ordinal(self, value):
|
||||
self.verify_ordinal(value)
|
||||
outwords = self.to_cardinal(value).split(" ")
|
||||
lastwords = outwords[-1].split("-")
|
||||
lastword = lastwords[-1].lower()
|
||||
try:
|
||||
lastword = self.ords[lastword]
|
||||
except KeyError:
|
||||
if lastword[-1] == "y":
|
||||
lastword = lastword[:-1] + "ie"
|
||||
lastword += "th"
|
||||
lastwords[-1] = self.title(lastword)
|
||||
outwords[-1] = "-".join(lastwords)
|
||||
return " ".join(outwords)
|
||||
|
||||
|
||||
def to_ordinal_num(self, value):
|
||||
self.verify_ordinal(value)
|
||||
return "%s%s"%(value, self.to_ordinal(value)[-2:])
|
||||
|
||||
|
||||
def to_year(self, val, longval=True):
|
||||
if not (val//100)%10:
|
||||
return self.to_cardinal(val)
|
||||
return self.to_splitnum(val, hightxt="hundred", jointxt="and",
|
||||
longval=longval)
|
||||
|
||||
def to_currency(self, val, longval=True):
|
||||
return self.to_splitnum(val, hightxt="dollar/s", lowtxt="cent/s",
|
||||
jointxt="and", longval=longval)
|
||||
|
||||
|
||||
n2w = Num2Word_EN()
|
||||
to_card = n2w.to_cardinal
|
||||
to_ord = n2w.to_ordinal
|
||||
to_ordnum = n2w.to_ordinal_num
|
||||
to_year = n2w.to_year
|
||||
|
||||
def main():
|
||||
for val in [ 1, 11, 12, 21, 31, 33, 71, 80, 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,
|
||||
-21212121211221211111, -2.121212, -1.0000100]:
|
||||
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)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
62
pynum2word/num2word_EN_EUR.py
Normal file
62
pynum2word/num2word_EN_EUR.py
Normal file
@@ -0,0 +1,62 @@
|
||||
'''
|
||||
Module: num2word_EN_EUR.py
|
||||
Requires: num2word_EN.py
|
||||
Version: 1.0
|
||||
|
||||
Author:
|
||||
Taro Ogawa (tso@users.sourceforge.org)
|
||||
|
||||
Copyright:
|
||||
Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
|
||||
|
||||
Licence:
|
||||
This module is distributed under the Lesser General Public Licence.
|
||||
http://www.opensource.org/licenses/lgpl-license.php
|
||||
|
||||
Data from:
|
||||
http://www.uni-bonn.de/~manfear/large.php
|
||||
|
||||
Usage:
|
||||
from num2word_EN import n2w, to_card, to_ord, to_ordnum
|
||||
to_card(1234567890)
|
||||
n2w.is_title = True
|
||||
to_card(1234567890)
|
||||
to_ord(1234567890)
|
||||
to_ordnum(1234567890)
|
||||
to_year(1976)
|
||||
to_currency(euros*100 + cents)
|
||||
to_currency((euros,cents))
|
||||
|
||||
|
||||
'''
|
||||
|
||||
from num2word_EN import Num2Word_EN
|
||||
|
||||
|
||||
class Num2Word_EN_EUR(Num2Word_EN):
|
||||
def to_currency(self, val, longval=True):
|
||||
return self.to_splitnum(val, hightxt="euro/s", lowtxt="cents",
|
||||
jointxt="and", longval=longval)
|
||||
|
||||
|
||||
n2w = Num2Word_EN_EUR()
|
||||
to_card = n2w.to_cardinal
|
||||
to_ord = n2w.to_ordinal
|
||||
to_ordnum = n2w.to_ordinal_num
|
||||
to_year = n2w.to_year
|
||||
to_currency = n2w.to_currency
|
||||
|
||||
def main():
|
||||
for val in [ 1, 11, 12, 21, 31, 33, 71, 80, 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,
|
||||
-21212121211221211111, -2.121212, -1.0000100]:
|
||||
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)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
63
pynum2word/num2word_EN_GB.py
Normal file
63
pynum2word/num2word_EN_GB.py
Normal file
@@ -0,0 +1,63 @@
|
||||
'''
|
||||
Module: num2word_EN_GB.py
|
||||
Requires: num2word_EN.py
|
||||
Version: 1.0
|
||||
|
||||
Author:
|
||||
Taro Ogawa (tso@users.sourceforge.org)
|
||||
|
||||
Copyright:
|
||||
Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
|
||||
|
||||
Licence:
|
||||
This module is distributed under the Lesser General Public Licence.
|
||||
http://www.opensource.org/licenses/lgpl-license.php
|
||||
|
||||
Data from:
|
||||
http://www.uni-bonn.de/~manfear/large.php
|
||||
|
||||
Usage:
|
||||
from num2word_EN import n2w, to_card, to_ord, to_ordnum
|
||||
to_card(1234567890)
|
||||
n2w.is_title = True
|
||||
to_card(1234567890)
|
||||
to_ord(1234567890)
|
||||
to_ordnum(1234567890)
|
||||
to_year(1976)
|
||||
to_currency(pounds*100 + pence)
|
||||
to_currency((pounds,pence))
|
||||
|
||||
|
||||
History:
|
||||
1.0: Split from num2word_EN with the addition of to_currency()
|
||||
'''
|
||||
|
||||
from num2word_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",
|
||||
jointxt="and", longval=longval)
|
||||
|
||||
|
||||
n2w = Num2Word_EN_GB()
|
||||
to_card = n2w.to_cardinal
|
||||
to_ord = n2w.to_ordinal
|
||||
to_ordnum = n2w.to_ordinal_num
|
||||
to_year = n2w.to_year
|
||||
|
||||
def main():
|
||||
for val in [ 1, 11, 12, 21, 31, 33, 71, 80, 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,
|
||||
-21212121211221211111, -2.121212, -1.0000100]:
|
||||
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)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
55
pynum2word/num2word_EN_GB_old.py
Normal file
55
pynum2word/num2word_EN_GB_old.py
Normal file
@@ -0,0 +1,55 @@
|
||||
'''
|
||||
Module: num2word_EN_GB_old.py
|
||||
Requires: num2word_EN_GB_old.py
|
||||
Version: 0.3
|
||||
|
||||
Author:
|
||||
Taro Ogawa (tso@users.sourceforge.org)
|
||||
|
||||
Copyright:
|
||||
Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
|
||||
|
||||
Licence:
|
||||
This module is distributed under the Lesser General Public Licence.
|
||||
http://www.opensource.org/licenses/lgpl-license.php
|
||||
|
||||
Usage:
|
||||
from num2word_EN_old import to_card, to_ord, to_ordnum
|
||||
to_card(1234567890)
|
||||
to_ord(1234567890)
|
||||
to_ordnum(12)
|
||||
|
||||
History:
|
||||
0.3: Rename from num2word_EN_old
|
||||
|
||||
Todo:
|
||||
Currency (pounds/shillings/pence)
|
||||
'''
|
||||
from num2word_EN_GB import Num2Word_EN_GB
|
||||
|
||||
class Num2Word_EN_GB_old(Num2Word_EN_GB):
|
||||
def base_setup(self):
|
||||
sclass = super(Num2Word_EN_GB, self)
|
||||
self.set_high_numwords = sclass.set_high_numwords
|
||||
sclass.base_setup()
|
||||
|
||||
|
||||
n2w = Num2Word_EN_GB_old()
|
||||
to_card = n2w.to_cardinal
|
||||
to_ord = n2w.to_ordinal
|
||||
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,
|
||||
180, 300, 308, 832, 1000, 1001, 1061, 1100, 1500, 1701, 3000,
|
||||
8280, 8291, 150000, 500000, 1000000, 2000000, 2000001,
|
||||
-21212121211221211111, -2.121212, -1.0000100]:
|
||||
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)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
147
pynum2word/num2word_ES.py
Normal file
147
pynum2word/num2word_ES.py
Normal file
@@ -0,0 +1,147 @@
|
||||
'''
|
||||
Module: num2word_ES.py
|
||||
Requires: num2word_EU.py
|
||||
Version: 0.3
|
||||
|
||||
Author:
|
||||
Taro Ogawa (tso@users.sourceforge.org)
|
||||
|
||||
Copyright:
|
||||
Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
|
||||
|
||||
Licence:
|
||||
This module is distributed under the Lesser General Public Licence.
|
||||
http://www.opensource.org/licenses/lgpl-license.php
|
||||
|
||||
Data from:
|
||||
http://www.smartphrase.com/Spanish/sp_numbers_voc.shtml
|
||||
|
||||
Usage:
|
||||
from num2word_ES import to_card, to_ord, to_ordnum
|
||||
to_card(1234567890)
|
||||
to_ord(1234567890)
|
||||
to_ordnum(12)
|
||||
|
||||
History:
|
||||
0.3: Use high ascii characters instead of low ascii approximations
|
||||
String interpolation where it makes things clearer
|
||||
add to_currency()
|
||||
'''
|
||||
from num2word_EU import Num2Word_EU
|
||||
|
||||
#//TODO: correct orthographics
|
||||
#//TODO: error messages
|
||||
|
||||
class Num2Word_ES(Num2Word_EU):
|
||||
|
||||
#//CHECK: Is this sufficient??
|
||||
def set_high_numwords(self, high):
|
||||
max = 3 + 6*len(high)
|
||||
|
||||
for word, n in zip(high, range(max, 3, -6)):
|
||||
self.cards[10**(n-3)] = word + "ill\xf2n"
|
||||
|
||||
|
||||
def setup(self):
|
||||
lows = ["cuatr", "tr", "b", "m"]
|
||||
self.high_numwords = self.gen_high_numwords([], [], lows)
|
||||
self.negword = "menos "
|
||||
self.pointword = "punto"
|
||||
self.errmsg_nonnum = "Only numbers may be converted to words."
|
||||
self.errmsg_toobig = "Number is too large to convert to words."
|
||||
self.gender_stem = "o"
|
||||
self.exclude_title = ["y", "menos", "punto"]
|
||||
self.mid_numwords = [(1000, "mil"), (100, "cien"), (90, "noventa"),
|
||||
(80, "ochenta"), (70, "setenta"), (60, "sesenta"),
|
||||
(50,"cincuenta"), (40,"cuarenta")]
|
||||
self.low_numwords = ["vientinueve", "vientiocho", "vientisiete",
|
||||
"vientis\xE8is", "vienticinco", "vienticuatro",
|
||||
"vientitr\xE8s", "vientid\xF2s", "vientiuno",
|
||||
"viente", "diecinueve", "dieciocho", "diecisiete",
|
||||
"dieciseis", "quince", "catorce", "trece", "doce",
|
||||
"once", "diez", "nueve", "ocho", "siete", "seis",
|
||||
"cinco", "cuatro", "tres", "dos", "uno", "cero"]
|
||||
self.ords = { 1 : "primer",
|
||||
2 : "segund",
|
||||
3 : "tercer",
|
||||
4 : "cuart",
|
||||
5 : "quint",
|
||||
6 : "sext",
|
||||
7 : "s\xE8ptim",
|
||||
8 : "octav",
|
||||
9 : "noven",
|
||||
10 : "d\xE8cim" }
|
||||
|
||||
|
||||
def merge(self, curr, next):
|
||||
ctext, cnum, ntext, nnum = curr + next
|
||||
|
||||
if cnum == 1:
|
||||
if nnum < 1000000:
|
||||
return next
|
||||
ctext = "un"
|
||||
elif cnum == 100:
|
||||
ctext += "t" + self.gender_stem
|
||||
|
||||
if nnum < cnum:
|
||||
if cnum < 100:
|
||||
return ("%s y %s"%(ctext, ntext), cnum + nnum)
|
||||
return ("%s %s"%(ctext, ntext), cnum + nnum)
|
||||
elif (not nnum % 1000000) and cnum > 1:
|
||||
ntext = ntext[:-3] + "ones"
|
||||
|
||||
if nnum == 100:
|
||||
if cnum == 5:
|
||||
ctext = "quinien"
|
||||
ntext = ""
|
||||
elif cnum == 7:
|
||||
ctext = "sete"
|
||||
elif cnum == 9:
|
||||
ctext = "nove"
|
||||
ntext += "t" + self.gender_stem + "s"
|
||||
else:
|
||||
ntext = " " + ntext
|
||||
|
||||
return (ctext + ntext, cnum * nnum)
|
||||
|
||||
|
||||
def to_ordinal(self, value):
|
||||
self.verify_ordinal(value)
|
||||
try:
|
||||
return self.ords[value] + self.gender_stem
|
||||
except KeyError:
|
||||
return self.to_cardinal(value)
|
||||
|
||||
def to_ordinal_num(self, value):
|
||||
self.verify_ordinal(value)
|
||||
# Correct for fem?
|
||||
return "%s\xB0"%value
|
||||
|
||||
|
||||
def to_currency(self, val, longval=True, old=False):
|
||||
if old:
|
||||
return self.to_splitnum(val, hightxt="peso/s", lowtxt="peseta/s",
|
||||
divisor=1000, jointxt="y", longval=longval)
|
||||
return super(Num2Word_ES, self).to_currency(val, jointxt="y",
|
||||
longval=longval)
|
||||
|
||||
|
||||
n2w = Num2Word_ES()
|
||||
to_card = n2w.to_cardinal
|
||||
to_ord = n2w.to_ordinal
|
||||
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,
|
||||
180, 300, 308, 832, 1000, 1001, 1061, 1100, 1500, 1701, 3000,
|
||||
8280, 8291, 150000, 500000, 1000000, 2000000, 2000001,
|
||||
-21212121211221211111, -2.121212, -1.0000100]:
|
||||
n2w.test(val)
|
||||
|
||||
n2w.test(1325325436067876801768700107601001012212132143210473207540327057320957032975032975093275093275093270957329057320975093272950730)
|
||||
print n2w.to_currency(1222)
|
||||
print n2w.to_currency(1222, old=True)
|
||||
print n2w.to_year(1222)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
44
pynum2word/num2word_EU.py
Normal file
44
pynum2word/num2word_EU.py
Normal file
@@ -0,0 +1,44 @@
|
||||
'''
|
||||
Module: num2word_EU.py
|
||||
Requires: num2word_base.py
|
||||
Version: 1.1
|
||||
|
||||
Author:
|
||||
Taro Ogawa (tso@users.sourceforge.org)
|
||||
|
||||
Copyright:
|
||||
Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
|
||||
|
||||
Licence:
|
||||
This module is distributed under the Lesser General Public Licence.
|
||||
http://www.opensource.org/licenses/lgpl-license.php
|
||||
|
||||
Data from:
|
||||
http://www.uni-bonn.de/~manfear/large.php
|
||||
|
||||
History:
|
||||
1.1: add to_currency()
|
||||
'''
|
||||
from num2word_base import Num2Word_Base
|
||||
|
||||
class Num2Word_EU(Num2Word_Base):
|
||||
def set_high_numwords(self, high):
|
||||
max = 3 + 6*len(high)
|
||||
|
||||
for word, n in zip(high, range(max, 3, -6)):
|
||||
self.cards[10**n] = word + "illiard"
|
||||
self.cards[10**(n-3)] = word + "illion"
|
||||
|
||||
|
||||
def base_setup(self):
|
||||
lows = ["non","oct","sept","sext","quint","quadr","tr","b","m"]
|
||||
units = ["", "un", "duo", "tre", "quattuor", "quin", "sex", "sept",
|
||||
"octo", "novem"]
|
||||
tens = ["dec", "vigint", "trigint", "quadragint", "quinquagint",
|
||||
"sexagint", "septuagint", "octogint", "nonagint"]
|
||||
self.high_numwords = ["cent"]+self.gen_high_numwords(units, tens, lows)
|
||||
|
||||
def to_currency(self, val, longval=True, jointxt=""):
|
||||
return self.to_splitnum(val, hightxt="Euro/s", lowtxt="Euro cent/s",
|
||||
jointxt=jointxt, longval=longval)
|
||||
|
||||
119
pynum2word/num2word_FR.py
Normal file
119
pynum2word/num2word_FR.py
Normal file
@@ -0,0 +1,119 @@
|
||||
'''
|
||||
Module: num2word_FR.py
|
||||
Requires: num2word_EU.py
|
||||
Version: 0.5
|
||||
|
||||
Author:
|
||||
Taro Ogawa (tso@users.sourceforge.org)
|
||||
|
||||
Copyright:
|
||||
Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
|
||||
|
||||
Licence:
|
||||
This module is distributed under the Lesser General Public Licence.
|
||||
http://www.opensource.org/licenses/lgpl-license.php
|
||||
|
||||
Data from:
|
||||
http://www.ouc.bc.ca/mola/fr/handouts/numbers.doc
|
||||
http://www.realfrench.net/units/Interunit_63.html
|
||||
http://www.sover.net/~daxtell/france/Euro/euro.htm
|
||||
|
||||
Usage:
|
||||
from num2word_FR import to_card, to_ord, to_ordnum
|
||||
to_card(1234567890)
|
||||
to_ord(1234567890)
|
||||
to_ordnum(12)
|
||||
|
||||
History:
|
||||
0.5: Use high ascii characters instead of low ascii approximations
|
||||
String interpolation where it makes things clearer
|
||||
to_currency() added [to_year works by default]
|
||||
'''
|
||||
from num2word_EU import Num2Word_EU
|
||||
|
||||
#//TODO: error messages in French
|
||||
#//TODO: ords
|
||||
class Num2Word_FR(Num2Word_EU):
|
||||
def setup(self):
|
||||
self.negword = "moins "
|
||||
self.pointword = "virgule"
|
||||
self.errmsg_nonnum = "Only numbers may be converted to words."
|
||||
self.errmsg_toobig = "Number is too large to convert to words."
|
||||
self.exclude_title = ["et", "virgule", "moins"]
|
||||
self.mid_numwords = [(1000, "mille"), (100, "cent"),
|
||||
(80, "quatre-vingts"), (60, "soixante"),
|
||||
(50, "cinquante"), (40, "quarante"),
|
||||
(30, "trente")]
|
||||
self.low_numwords = ["vingt", "dix-neuf", "dix-huit", "dix-sept",
|
||||
"seize", "quinze", "quatorze", "treize", "douze",
|
||||
"onze", "dix", "neuf", "huit", "sept", "six",
|
||||
"cinq", "quatre", "trois", "deux", "un", "z\xE8ro"]
|
||||
|
||||
|
||||
def merge(self, curr, next):
|
||||
ctext, cnum, ntext, nnum = curr + next
|
||||
|
||||
if cnum == 1:
|
||||
if nnum < 1000000:
|
||||
return next
|
||||
else:
|
||||
if (not (cnum - 80)%100 or not cnum%100) and ctext[-1] == "s":
|
||||
ctext = ctext[:-1]
|
||||
if (cnum<1000 and nnum <> 1000 and ntext[-1] <> "s"
|
||||
and not nnum%100):
|
||||
ntext += "s"
|
||||
|
||||
if nnum < cnum < 100:
|
||||
if nnum % 10 == 1 and cnum <> 80:
|
||||
return ("%s et %s"%(ctext, ntext), cnum + nnum)
|
||||
return ("%s-%s"%(ctext, ntext), cnum + nnum)
|
||||
elif nnum > cnum:
|
||||
return ("%s %s"%(ctext, ntext), cnum * nnum)
|
||||
return ("%s %s"%(ctext, ntext), cnum + nnum)
|
||||
|
||||
|
||||
# Is this right for such things as 1001 - "mille uni<6E>me" instead of
|
||||
# "mille premier"?? "milli<6C>me"??
|
||||
|
||||
def to_ordinal(self,value):
|
||||
self.verify_ordinal(value)
|
||||
if value == 1:
|
||||
return "premier"
|
||||
word = self.to_cardinal(value)
|
||||
if word[-1] == "e":
|
||||
word = word[:-1]
|
||||
return word + "i\xE8me"
|
||||
|
||||
|
||||
def to_ordinal_num(self, value):
|
||||
self.verify_ordinal(value)
|
||||
out = str(value)
|
||||
out += {"1" : "er" }.get(out[-1], "me")
|
||||
return out
|
||||
|
||||
def to_currency(self, val, longval=True, old=False):
|
||||
hightxt = "Euro/s"
|
||||
if old:
|
||||
hightxt="franc/s"
|
||||
return self.to_splitnum(val, hightxt=hightxt, lowtxt="centime/s",
|
||||
jointxt="et",longval=longval)
|
||||
|
||||
n2w = Num2Word_FR()
|
||||
to_card = n2w.to_cardinal
|
||||
to_ord = n2w.to_ordinal
|
||||
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,
|
||||
180, 300, 308, 832, 1000, 1001, 1061, 1100, 1500, 1701, 3000,
|
||||
8280, 8291, 150000, 500000, 1000000, 2000000, 2000001,
|
||||
-21212121211221211111, -2.121212, -1.0000100]:
|
||||
n2w.test(val)
|
||||
|
||||
n2w.test(1325325436067876801768700107601001012212132143210473207540327057320957032975032975093275093275093270957329057320975093272950730)
|
||||
print n2w.to_currency(112121)
|
||||
print n2w.to_year(1996)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
213
pynum2word/num2word_LT.py
Normal file
213
pynum2word/num2word_LT.py
Normal file
@@ -0,0 +1,213 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
u"""
|
||||
>>> from textwrap import fill
|
||||
|
||||
>>> ' '.join([str(i) for i in splitby3('1')])
|
||||
'1'
|
||||
>>> ' '.join([str(i) for i in splitby3('1123')])
|
||||
'1 123'
|
||||
>>> ' '.join([str(i) for i in splitby3('1234567890')])
|
||||
'1 234 567 890'
|
||||
|
||||
>>> print(' '.join([n2w(i) for i in range(10)]))
|
||||
nulis vienas du trys keturi penki šeši septyni aštuoni devyni
|
||||
|
||||
>>> print(fill(' '.join([n2w(i+10) for i in range(10)])))
|
||||
dešimt vienuolika dvylika trylika keturiolika penkiolika šešiolika
|
||||
septyniolika aštuoniolika devyniolika
|
||||
|
||||
>>> print(fill(' '.join([n2w(i*10) for i in range(10)])))
|
||||
nulis dešimt dvidešimt trisdešimt keturiasdešimt penkiasdešimt
|
||||
šešiasdešimt septyniasdešimt aštuoniasdešimt devyniasdešimt
|
||||
|
||||
>>> print(n2w(100))
|
||||
šimtas
|
||||
>>> print(n2w(101))
|
||||
šimtas vienas
|
||||
>>> print(n2w(110))
|
||||
šimtas dešimt
|
||||
>>> print(n2w(115))
|
||||
šimtas penkiolika
|
||||
>>> print(n2w(123))
|
||||
šimtas dvidešimt trys
|
||||
>>> print(n2w(1000))
|
||||
tūkstantis
|
||||
>>> print(n2w(1001))
|
||||
tūkstantis vienas
|
||||
>>> print(n2w(2012))
|
||||
du tūkstančiai dvylika
|
||||
|
||||
>>> print(fill(n2w(1234567890)))
|
||||
milijardas du šimtai trisdešimt keturi milijonai penki šimtai
|
||||
šešiasdešimt septyni tūkstančiai aštuoni šimtai devyniasdešimt
|
||||
|
||||
>>> print(fill(n2w(215461407892039002157189883901676)))
|
||||
du šimtai penkiolika naintilijonų keturi šimtai šešiasdešimt vienas
|
||||
oktilijonas keturi šimtai septyni septilijonai aštuoni šimtai
|
||||
devyniasdešimt du sikstilijonai trisdešimt devyni kvintilijonai du
|
||||
kvadrilijonai šimtas penkiasdešimt septyni trilijonai šimtas
|
||||
aštuoniasdešimt devyni milijardai aštuoni šimtai aštuoniasdešimt trys
|
||||
milijonai devyni šimtai vienas tūkstantis šeši šimtai septyniasdešimt
|
||||
šeši
|
||||
|
||||
>>> print(fill(n2w(719094234693663034822824384220291)))
|
||||
septyni šimtai devyniolika naintilijonų devyniasdešimt keturi
|
||||
oktilijonai du šimtai trisdešimt keturi septilijonai šeši šimtai
|
||||
devyniasdešimt trys sikstilijonai šeši šimtai šešiasdešimt trys
|
||||
kvintilijonai trisdešimt keturi kvadrilijonai aštuoni šimtai dvidešimt
|
||||
du trilijonai aštuoni šimtai dvidešimt keturi milijardai trys šimtai
|
||||
aštuoniasdešimt keturi milijonai du šimtai dvidešimt tūkstančių du
|
||||
šimtai devyniasdešimt vienas
|
||||
|
||||
# TODO: fix this:
|
||||
>>> print(fill(n2w(1000000000000000000000000000000)))
|
||||
naintilijonas
|
||||
|
||||
>>> print(to_currency(1, 'LTL'))
|
||||
vienas litas, nulis centų
|
||||
|
||||
>>> print(to_currency(1234.56, 'LTL'))
|
||||
tūkstantis du šimtai trisdešimt keturi litai, penkiasdešimt šeši centai
|
||||
|
||||
"""
|
||||
|
||||
ZERO = (u'nulis',)
|
||||
|
||||
ONES = {
|
||||
1: (u'vienas',),
|
||||
2: (u'du',),
|
||||
3: (u'trys',),
|
||||
4: (u'keturi',),
|
||||
5: (u'penki',),
|
||||
6: (u'šeši',),
|
||||
7: (u'septyni',),
|
||||
8: (u'aštuoni',),
|
||||
9: (u'devyni',),
|
||||
}
|
||||
|
||||
TENS = {
|
||||
0: (u'dešimt',),
|
||||
1: (u'vienuolika',),
|
||||
2: (u'dvylika',),
|
||||
3: (u'trylika',),
|
||||
4: (u'keturiolika',),
|
||||
5: (u'penkiolika',),
|
||||
6: (u'šešiolika',),
|
||||
7: (u'septyniolika',),
|
||||
8: (u'aštuoniolika',),
|
||||
9: (u'devyniolika',),
|
||||
}
|
||||
|
||||
TWENTIES = {
|
||||
2: (u'dvidešimt',),
|
||||
3: (u'trisdešimt',),
|
||||
4: (u'keturiasdešimt',),
|
||||
5: (u'penkiasdešimt',),
|
||||
6: (u'šešiasdešimt',),
|
||||
7: (u'septyniasdešimt',),
|
||||
8: (u'aštuoniasdešimt',),
|
||||
9: (u'devyniasdešimt',),
|
||||
}
|
||||
|
||||
HUNDRED = (u'šimtas', u'šimtai')
|
||||
|
||||
THOUSANDS = {
|
||||
1: (u'tūkstantis', u'tūkstančiai', u'tūkstančių'),
|
||||
2: (u'milijonas', u'milijonai', u'milijonų'),
|
||||
3: (u'milijardas', u'milijardai', u'milijardų'),
|
||||
4: (u'trilijonas', u'trilijonai', u'trilijonų'),
|
||||
5: (u'kvadrilijonas', u'kvadrilijonai', u'kvadrilijonų'),
|
||||
6: (u'kvintilijonas', u'kvintilijonai', u'kvintilijonų'),
|
||||
7: (u'sikstilijonas', u'sikstilijonai', u'sikstilijonų'),
|
||||
8: (u'septilijonas', u'septilijonai', u'septilijonų'),
|
||||
9: (u'oktilijonas', u'oktilijonai', u'oktilijonų'),
|
||||
10: (u'naintilijonas', u'naintilijonai', u'naintilijonų'),
|
||||
}
|
||||
|
||||
CURRENCIES = {
|
||||
'LTL': ((u'litas', u'litai', u'litų'), (u'centas', u'centai', u'centų')),
|
||||
}
|
||||
|
||||
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):
|
||||
n1, n2, n3 = get_digits(n)
|
||||
if n2 == 1 or n1 == 0 or n == 0:
|
||||
return forms[2]
|
||||
elif n1 == 1:
|
||||
return forms[0]
|
||||
else:
|
||||
return forms[1]
|
||||
|
||||
def int2word(n):
|
||||
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)
|
||||
|
||||
if n3 > 0:
|
||||
if n3 > 1:
|
||||
words.append(ONES[n3][0])
|
||||
words.append(HUNDRED[1])
|
||||
else:
|
||||
words.append(HUNDRED[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:
|
||||
words.append(pluralize(x, THOUSANDS[i]))
|
||||
|
||||
return ' '.join(words)
|
||||
|
||||
def n2w(n):
|
||||
n = str(n).replace(',', '.')
|
||||
if '.' in n:
|
||||
left, right = n.split('.')
|
||||
return u'%s kablelis %s' % (int2word(int(left)), int2word(int(right)))
|
||||
else:
|
||||
return int2word(int(n))
|
||||
|
||||
def to_currency(n, currency='LTL'):
|
||||
if type(n) == int:
|
||||
left = n / 100
|
||||
right = n % 100
|
||||
else:
|
||||
n = str(n).replace(',', '.')
|
||||
if '.' in n:
|
||||
left, right = n.split('.')
|
||||
else:
|
||||
left, right = n, 0
|
||||
left, right = int(left), int(right)
|
||||
cr1, cr2 = CURRENCIES[currency]
|
||||
return u'%s %s, %s %s' % (int2word(left), pluralize(left, cr1),
|
||||
int2word(right), pluralize(right, cr2))
|
||||
|
||||
to_card = n2w
|
||||
|
||||
if __name__ == '__main__':
|
||||
import doctest
|
||||
doctest.testmod()
|
||||
266
pynum2word/num2word_base.py
Normal file
266
pynum2word/num2word_base.py
Normal file
@@ -0,0 +1,266 @@
|
||||
'''
|
||||
Module: num2word_base.py
|
||||
Version: 1.0
|
||||
|
||||
Author:
|
||||
Taro Ogawa (tso@users.sourceforge.org)
|
||||
|
||||
Copyright:
|
||||
Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
|
||||
|
||||
Licence:
|
||||
This module is distributed under the Lesser General Public Licence.
|
||||
http://www.opensource.org/licenses/lgpl-license.php
|
||||
|
||||
History:
|
||||
1.1: add to_splitnum() and inflect()
|
||||
add to_year() and to_currency() stubs
|
||||
'''
|
||||
|
||||
|
||||
from __future__ import generators
|
||||
from orderedmapping import OrderedMapping
|
||||
|
||||
|
||||
class Num2Word_Base(object):
|
||||
def __init__(self):
|
||||
self.cards = OrderedMapping()
|
||||
self.is_title = False
|
||||
self.precision = 2
|
||||
self.exclude_title = []
|
||||
self.negword = "(-) "
|
||||
self.pointword = "(.)"
|
||||
self.errmsg_nonnum = "type(%s) not in [long, int, float]"
|
||||
self.errmsg_floatord = "Cannot treat float %s as ordinal."
|
||||
self.errmsg_negord = "Cannot treat negative num %s as ordinal."
|
||||
self.errmsg_toobig = "abs(%s) must be less than %s."
|
||||
|
||||
self.base_setup()
|
||||
self.setup()
|
||||
self.set_numwords()
|
||||
|
||||
self.MAXVAL = 1000 * self.cards.order[0]
|
||||
|
||||
|
||||
def set_numwords(self):
|
||||
self.set_high_numwords(self.high_numwords)
|
||||
self.set_mid_numwords(self.mid_numwords)
|
||||
self.set_low_numwords(self.low_numwords)
|
||||
|
||||
|
||||
def gen_high_numwords(self, units, tens, lows):
|
||||
out = [u + t for t in tens for u in units]
|
||||
out.reverse()
|
||||
return out + lows
|
||||
|
||||
|
||||
def set_mid_numwords(self, mid):
|
||||
for key, val in mid:
|
||||
self.cards[key] = val
|
||||
|
||||
|
||||
def set_low_numwords(self, numwords):
|
||||
for word, n in zip(numwords, range(len(numwords) - 1, -1, -1)):
|
||||
self.cards[n] = word
|
||||
|
||||
|
||||
def splitnum(self, value):
|
||||
for elem in self.cards:
|
||||
if elem > value:
|
||||
continue
|
||||
|
||||
out = []
|
||||
if value == 0:
|
||||
div, mod = 1, 0
|
||||
else:
|
||||
div, mod = divmod(value, elem)
|
||||
|
||||
if div == 1:
|
||||
out.append((self.cards[1], 1))
|
||||
else:
|
||||
if div == value: # The system tallies, eg Roman Numerals
|
||||
return [(div * self.cards[elem], div*elem)]
|
||||
out.append(self.splitnum(div))
|
||||
|
||||
out.append((self.cards[elem], elem))
|
||||
|
||||
if mod:
|
||||
out.append(self.splitnum(mod))
|
||||
|
||||
return out
|
||||
|
||||
|
||||
def to_cardinal(self, value):
|
||||
try:
|
||||
assert long(value) == value
|
||||
except (ValueError, TypeError, AssertionError):
|
||||
return self.to_cardinal_float(value)
|
||||
|
||||
self.verify_num(value)
|
||||
|
||||
out = ""
|
||||
if value < 0:
|
||||
value = abs(value)
|
||||
out = self.negword
|
||||
|
||||
if value >= self.MAXVAL:
|
||||
raise OverflowError(self.errmsg_toobig % (value, self.MAXVAL))
|
||||
|
||||
|
||||
val = self.splitnum(value)
|
||||
words, num = self.clean(val)
|
||||
return self.title(out + words)
|
||||
|
||||
|
||||
def to_cardinal_float(self, value):
|
||||
try:
|
||||
float(value) == value
|
||||
except (ValueError, TypeError, AssertionError):
|
||||
raise TypeError(self.errmsg_nonnum % value)
|
||||
|
||||
pre = int(value)
|
||||
post = abs(value - pre)
|
||||
|
||||
out = [self.to_cardinal(pre)]
|
||||
if self.precision:
|
||||
out.append(self.title(self.pointword))
|
||||
|
||||
for i in range(self.precision):
|
||||
post *= 10
|
||||
curr = int(post)
|
||||
out.append(str(self.to_cardinal(curr)))
|
||||
post -= curr
|
||||
|
||||
return " ".join(out)
|
||||
|
||||
|
||||
def merge(self, curr, next):
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
def clean(self, val):
|
||||
out = val
|
||||
while len(val) != 1:
|
||||
out = []
|
||||
left, right = val[:2]
|
||||
if isinstance(left, tuple) and isinstance(right, tuple):
|
||||
out.append(self.merge(left, right))
|
||||
if val[2:]:
|
||||
out.append(val[2:])
|
||||
else:
|
||||
for elem in val:
|
||||
if isinstance(elem, list):
|
||||
if len(elem) == 1:
|
||||
out.append(elem[0])
|
||||
else:
|
||||
out.append(self.clean(elem))
|
||||
else:
|
||||
out.append(elem)
|
||||
val = out
|
||||
return out[0]
|
||||
|
||||
|
||||
def title(self, value):
|
||||
if self.is_title:
|
||||
out = []
|
||||
value = value.split()
|
||||
for word in value:
|
||||
if word in self.exclude_title:
|
||||
out.append(word)
|
||||
else:
|
||||
out.append(word[0].upper() + word[1:])
|
||||
value = " ".join(out)
|
||||
return value
|
||||
|
||||
|
||||
def verify_ordinal(self, value):
|
||||
if not value == long(value):
|
||||
raise TypeError, self.errmsg_floatord %(value)
|
||||
if not abs(value) == value:
|
||||
raise TypeError, self.errmsg_negord %(value)
|
||||
|
||||
|
||||
def verify_num(self, value):
|
||||
return 1
|
||||
|
||||
|
||||
def set_wordnums(self):
|
||||
pass
|
||||
|
||||
|
||||
def to_ordinal(value):
|
||||
return self.to_cardinal(value)
|
||||
|
||||
|
||||
def to_ordinal_num(self, value):
|
||||
return value
|
||||
|
||||
|
||||
# Trivial version
|
||||
def inflect(self, value, text):
|
||||
text = text.split("/")
|
||||
if value == 1:
|
||||
return text[0]
|
||||
return "".join(text)
|
||||
|
||||
|
||||
#//CHECK: generalise? Any others like pounds/shillings/pence?
|
||||
def to_splitnum(self, val, hightxt="", lowtxt="", jointxt="",
|
||||
divisor=100, longval=True):
|
||||
out = []
|
||||
try:
|
||||
high, low = val
|
||||
except TypeError:
|
||||
high, low = divmod(val, divisor)
|
||||
if high:
|
||||
hightxt = self.title(self.inflect(high, hightxt))
|
||||
out.append(self.to_cardinal(high))
|
||||
if low:
|
||||
if longval:
|
||||
if hightxt:
|
||||
out.append(hightxt)
|
||||
if jointxt:
|
||||
out.append(self.title(jointxt))
|
||||
elif hightxt:
|
||||
out.append(hightxt)
|
||||
if low:
|
||||
out.append(self.to_cardinal(low))
|
||||
if lowtxt and longval:
|
||||
out.append(self.title(self.inflect(low, lowtxt)))
|
||||
return " ".join(out)
|
||||
|
||||
|
||||
def to_year(self, value, **kwargs):
|
||||
return self.to_cardinal(value)
|
||||
|
||||
|
||||
def to_currency(self, value, **kwargs):
|
||||
return self.to_cardinal(value)
|
||||
|
||||
|
||||
def base_setup(self):
|
||||
pass
|
||||
|
||||
|
||||
def setup(self):
|
||||
pass
|
||||
|
||||
|
||||
def test(self, value):
|
||||
try:
|
||||
_card = self.to_cardinal(value)
|
||||
except:
|
||||
_card = "invalid"
|
||||
|
||||
try:
|
||||
_ord = self.to_ordinal(value)
|
||||
except:
|
||||
_ord = "invalid"
|
||||
|
||||
try:
|
||||
_ordnum = self.to_ordinal_num(value)
|
||||
except:
|
||||
_ordnum = "invalid"
|
||||
|
||||
print ("For %s, card is %s;\n\tord is %s; and\n\tordnum is %s." %
|
||||
(value, _card, _ord, _ordnum))
|
||||
34
pynum2word/orderedmapping.py
Normal file
34
pynum2word/orderedmapping.py
Normal file
@@ -0,0 +1,34 @@
|
||||
'''
|
||||
Module: orderedmapping.py
|
||||
Version: 1.0
|
||||
|
||||
Author:
|
||||
Taro Ogawa (tso@users.sourceforge.org)
|
||||
|
||||
Copyright:
|
||||
Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
|
||||
|
||||
Licence:
|
||||
This module is distributed under the Lesser General Public Licence.
|
||||
http://www.opensource.org/licenses/lgpl-license.php
|
||||
'''
|
||||
from __future__ import generators
|
||||
class OrderedMapping(dict):
|
||||
def __init__(self, *pairs):
|
||||
self.order = []
|
||||
for key, val in pairs:
|
||||
self[key] = val
|
||||
|
||||
def __setitem__(self, key, val):
|
||||
if key not in self:
|
||||
self.order.append(key)
|
||||
super(OrderedMapping, self).__setitem__(key, val)
|
||||
|
||||
def __iter__(self):
|
||||
for item in self.order:
|
||||
yield item
|
||||
|
||||
def __repr__(self):
|
||||
out = ["%s: %s"%(repr(item), repr(self[item])) for item in self]
|
||||
out = ", ".join(out)
|
||||
return "{%s}"%out
|
||||
Reference in New Issue
Block a user