Fix bugs in the float precision and the currency, increase test coverage (#134)

* Fix some bugs in the float precision and the currency, increase test coverage.

Ref: issue #112 #113

* Update README.rst
This commit is contained in:
Ernesto Rodriguez Ortiz
2017-11-06 20:19:26 -05:00
committed by GitHub
parent 5a131fedc6
commit 1c699d1bb4
15 changed files with 158 additions and 92 deletions

View File

@@ -45,9 +45,11 @@ There's only one function to use::
Besides the numerical argument, there's two optional arguments.
**to:** The converter to use. Supperted values are
**to:** The converter to use. Supperted values are:
* ``cardinal`` (default)
* ``ordinal``
* ``ordinal_num``
* ``year``
* ``currency``

View File

@@ -73,7 +73,7 @@ CONVERTER_CLASSES = {
}
CONVERTES_TYPES = ['cardinal', 'ordinal', 'year', 'currency']
CONVERTES_TYPES = ['cardinal', 'ordinal', 'ordinal_num', 'year', 'currency']
def num2words(number, ordinal=False, lang='en', to='cardinal', **kwargs):

View File

@@ -18,6 +18,7 @@ from __future__ import unicode_literals
import math
from collections import OrderedDict
from decimal import Decimal
from .compat import to_s
@@ -106,6 +107,10 @@ class Num2Word_Base(object):
def float2tuple(self, value):
pre = int(value)
# Simple way of finding decimal places to update the precision
self.precision = abs(Decimal(str(value)).as_tuple().exponent)
post = abs(value - pre) * 10**self.precision
if abs(round(post) - post) < 0.01:
# We generally floor all values beyond our precision (rather than

View File

@@ -91,7 +91,7 @@ class Num2Word_ES(Num2Word_EU):
if nnum < 1000000:
return next
ctext = "un"
elif cnum == 100 and not nnum == 1000:
elif cnum == 100 and not nnum % 1000 == 0:
ctext += "t" + self.gender_stem
if nnum < cnum:
@@ -117,7 +117,6 @@ class Num2Word_ES(Num2Word_EU):
def to_ordinal(self, value):
self.verify_ordinal(value)
text = ""
try:
if value == 0:
text = ""
@@ -167,31 +166,10 @@ class Num2Word_ES(Num2Word_EU):
return "%s%s" % (value, "º" if self.gender_stem == 'o' else "ª")
def to_currency(self, val, longval=True, old=False):
hightxt, lowtxt = "euro/s", "centavo/s"
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(13253254360678768017687001076010010122121321432104732075403270573)
print(n2w.to_currency(1222))
print(n2w.to_currency(1222, old=True))
print(n2w.to_year(1222))
if __name__ == "__main__":
main()
hightxt, lowtxt = "peso/s", "peseta/s"
result = self.to_splitnum(val, hightxt=hightxt, lowtxt=lowtxt,
divisor=1, jointxt="y", longval=longval)
# Handle exception, in spanish is "un euro" and not "uno euro"
return result.replace("uno", "un")

View File

@@ -24,28 +24,7 @@ from .lang_ES import Num2Word_ES
class Num2Word_ES_CO(Num2Word_ES):
def to_currency(self, val, longval=True, old=False):
return self.to_splitnum(val, hightxt="peso/s", lowtxt="peso/s",
divisor=1000, jointxt="y", longval=longval)
n2w = Num2Word_ES_CO()
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(13253254360678768017687001076010010122121321432104732075403270573)
print(n2w.to_currency(1222))
print(n2w.to_currency(1222, old=True))
print(n2w.to_year(1222))
if __name__ == "__main__":
main()
result = self.to_splitnum(val, hightxt="peso/s", lowtxt="centavo/s",
divisor=1, jointxt="y", longval=longval)
# Handle exception, in spanish is "un euro" and not "uno euro"
return result.replace("uno", "un")

View File

@@ -24,29 +24,10 @@ from .lang_ES import Num2Word_ES
class Num2Word_ES_VE(Num2Word_ES):
def to_currency(self, val, longval=True, old=False):
return self.to_splitnum(val, hightxt="bolívar/es Fuerte/s",
lowtxt="bolívar/es fuerte/s",
divisor=1000, jointxt="y", longval=longval)
n2w = Num2Word_ES_VE()
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(13253254360678768017687001076010010122121321432104732075403270573)
print(n2w.to_currency(1222))
print(n2w.to_currency(1222, old=True))
print(n2w.to_year(1222))
if __name__ == "__main__":
main()
hightxt = "bolívar/es" if old else "bolívar/es fuerte/s"
result = self.to_splitnum(
val, hightxt=hightxt, lowtxt="centavo/s",
divisor=1, jointxt="y", longval=longval
)
# Handle exception, in spanish is "un euro" and not "uno euro"
return result.replace("uno", "un")

View File

@@ -25,7 +25,7 @@ setup(
author='Taro Ogawa <tso at users sourceforge net>',
author_email='tos@users.sourceforge.net',
maintainer='Savoir-faire Linux inc.',
maintainer_email='virgil.dupras@savoirfairelinux.com',
maintainer_email='ernesto.rodriguezortiz@savoirfairelinux.com',
keywords=' number word numbers words convert conversion i18n '
'localisation localization internationalisation '
'internationalization',

View File

@@ -56,7 +56,9 @@ class Num2WordsDETest(TestCase):
self.assertEqual(num2words(4000000000, lang='de'), "vier milliarden")
def test_cardinal_for_decimal_number(self):
self.assertEqual(num2words(3.486, lang='de'), "drei Komma vier acht")
self.assertEqual(
num2words(3.486, lang='de'), "drei Komma vier acht sechs"
)
def test_ordinal_for_negative_numbers(self):
self.assertRaises(TypeError, num2words, -12, ordinal=True, lang='de')

View File

@@ -25,7 +25,7 @@ class Num2WordsENTest(TestCase):
def test_cardinal_for_float_number(self):
# issue 24
self.assertEqual(num2words(12.50), "twelve point five zero")
self.assertEqual(num2words(12.5), "twelve point five")
self.assertEqual(num2words(12.51), "twelve point five one")
self.assertEqual(num2words(12.53), "twelve point five three")
self.assertEqual(num2words(12.59), "twelve point five nine")

View File

@@ -23,30 +23,36 @@ TEST_CASES_CARDINAL = (
(1, 'uno'),
(2, 'dos'),
(3, 'tres'),
(5.5, 'cinco punto cinco'),
(11, 'once'),
(12, 'doce'),
(16, 'dieciseis'),
(17.42, 'diecisiete punto cuatro dos'),
(19, 'diecinueve'),
(20, 'veinte'),
(21, 'veintiuno'),
(26, 'veintiséis'),
(27.312, 'veintisiete punto tres uno dos'),
(28, 'veintiocho'),
(30, 'treinta'),
(31, 'treinta y uno'),
(40, 'cuarenta'),
(44, 'cuarenta y cuatro'),
(50, 'cincuenta'),
(53.486, 'cincuenta y tres punto cuatro ocho seis'),
(55, 'cincuenta y cinco'),
(60, 'sesenta'),
(67, 'sesenta y siete'),
(70, 'setenta'),
(79, 'setenta y nueve'),
(89, 'ochenta y nueve'),
(95, 'noventa y cinco'),
(100, 'cien'),
(101, 'ciento uno'),
(199, 'ciento noventa y nueve'),
(203, 'doscientos tres'),
(287, 'doscientos ochenta y siete'),
(300, 'trescientos'),
(300.42, 'trescientos punto cuatro dos'),
(356, 'trescientos cincuenta y seis'),
(400, 'cuatrocientos'),
(434, 'cuatrocientos treinta y cuatro'),
@@ -63,6 +69,7 @@ TEST_CASES_CARDINAL = (
(2385, 'dos mil trescientos ochenta y cinco'),
(3766, 'tres mil setecientos sesenta y seis'),
(4196, 'cuatro mil ciento noventa y seis'),
(4196.42, 'cuatro mil ciento noventa y seis punto cuatro dos'),
(5846, 'cinco mil ochocientos cuarenta y seis'),
(6459, 'seis mil cuatrocientos cincuenta y nueve'),
(7232, 'siete mil doscientos treinta y dos'),
@@ -70,6 +77,12 @@ TEST_CASES_CARDINAL = (
(9539, 'nueve mil quinientos treinta y nueve'),
(1000000, 'un millón'),
(1000001, 'un millón uno'),
(4000000, 'cuatro millones'),
(10000000000000, 'diez billones'),
(100000000000000, 'cien billones'),
(1000000000000000000, 'un trillón'),
(1000000000000000000000, 'mil trillones'),
(10000000000000000000000000, 'diez cuatrillones')
)
TEST_CASES_ORDINAL = (
@@ -79,6 +92,41 @@ TEST_CASES_ORDINAL = (
(14, 'décimo cuarto'),
(28, 'vigésimo octavo'),
(100, 'centésimo'),
(1000, 'milésimo'),
(1000000, 'millonésimo'),
(1000000000000000, 'cuadrillonésimo'),
(1000000000000000000, 'un trillón') # over 1e18 is not supported
)
TEST_CASES_ORDINAL_NUM = (
(1, ''),
(8, ''),
(12, '12º'),
(14, '14º'),
(28, '28º'),
(100, '100º'),
(1000, '1000º'),
(1000000, '1000000º')
)
TEST_CASES_TO_CURRENCY = (
(1, 'un euro'),
(2, 'dos euros'),
(8, 'ocho euros'),
(12, 'doce euros'),
(21, 'veintiun euros'),
(81.25, 'ochenta y un euros y veinticinco centavos'),
(100, 'cien euros'),
)
TEST_CASES_TO_CURRENCY_OLD = (
(1, 'un peso'),
(2, 'dos pesos'),
(8, 'ocho pesos'),
(12, 'doce pesos'),
(21, 'veintiun pesos'),
(81.25, 'ochenta y un pesos y veinticinco pesetas'),
(100, 'cien pesos'),
)
@@ -94,3 +142,24 @@ class Num2WordsESTest(TestCase):
num2words(test[0], lang='es', ordinal=True),
test[1]
)
def test_ordinal_num(self):
for test in TEST_CASES_ORDINAL_NUM:
self.assertEqual(
num2words(test[0], lang='es', to='ordinal_num'),
test[1]
)
def test_currency(self):
for test in TEST_CASES_TO_CURRENCY:
self.assertEqual(
num2words(test[0], lang='es', to='currency'),
test[1]
)
def test_currency_old(self):
for test in TEST_CASES_TO_CURRENCY_OLD:
self.assertEqual(
num2words(test[0], lang='es', to='currency', old=True),
test[1]
)

View File

@@ -20,6 +20,16 @@ from num2words import num2words
from . import test_es
TEST_CASES_TO_CURRENCY = (
(1, 'un peso'),
(2, 'dos pesos'),
(8, 'ocho pesos'),
(12, 'doce pesos'),
(21, 'veintiun pesos'),
(81.25, 'ochenta y un pesos y veinticinco centavos'),
(100, 'cien pesos'),
)
class Num2WordsESCOTest(test_es.Num2WordsESTest):
@@ -33,3 +43,17 @@ class Num2WordsESCOTest(test_es.Num2WordsESTest):
num2words(test[0], lang='es_CO', ordinal=True),
test[1]
)
def test_ordinal_num(self):
for test in test_es.TEST_CASES_ORDINAL_NUM:
self.assertEqual(
num2words(test[0], lang='es', to='ordinal_num'),
test[1]
)
def test_currency(self):
for test in TEST_CASES_TO_CURRENCY:
self.assertEqual(
num2words(test[0], lang='es_CO', to='currency'),
test[1]
)

View File

@@ -20,6 +20,16 @@ from num2words import num2words
from . import test_es
TEST_CASES_TO_CURRENCY = (
(1, 'un bolívar'),
(2, 'dos bolívares'),
(8, 'ocho bolívares'),
(12, 'doce bolívares'),
(21, 'veintiun bolívares'),
(81.25, 'ochenta y un bolívares y veinticinco centavos'),
(100, 'cien bolívares'),
)
class Num2WordsESVETest(test_es.Num2WordsESTest):
@@ -33,3 +43,17 @@ class Num2WordsESVETest(test_es.Num2WordsESTest):
num2words(test[0], lang='es_VE', ordinal=True),
test[1]
)
def test_ordinal_num(self):
for test in test_es.TEST_CASES_ORDINAL_NUM:
self.assertEqual(
num2words(test[0], lang='es', to='ordinal_num'),
test[1]
)
def test_currency(self):
for test in TEST_CASES_TO_CURRENCY:
self.assertEqual(
num2words(test[0], lang='es_VE', to='currency', old=True),
test[1]
)

View File

@@ -55,7 +55,9 @@ class Num2WordsNLTest(TestCase):
self.assertEqual(num2words(4000000000, lang='nl'), "vier miljard")
def test_cardinal_for_decimal_number(self):
self.assertEqual(num2words(3.486, lang='nl'), "drie komma vier acht")
self.assertEqual(
num2words(3.486, lang='nl'), "drie komma vier acht zes"
)
def test_ordinal_for_negative_numbers(self):
self.assertRaises(TypeError, num2words, -12, ordinal=True, lang='nl')

View File

@@ -105,14 +105,14 @@ class Num2WordsPTBRTest(TestCase):
self.assertEqual(num2words(
Decimal('1.01'), lang='pt_BR'), 'um vírgula zero um')
self.assertEqual(num2words(
Decimal('1.035'), lang='pt_BR'), 'um vírgula zero três'
Decimal('1.035'), lang='pt_BR'), 'um vírgula zero três cinco'
)
self.assertEqual(num2words(
Decimal('1.35'), lang='pt_BR'), 'um vírgula três cinco'
)
self.assertEqual(
num2words(Decimal('3.14159'), lang='pt_BR'),
'três vírgula um quatro'
'três vírgula um quatro um cinco nove'
)
self.assertEqual(
num2words(Decimal('101.22'), lang='pt_BR'),
@@ -332,14 +332,14 @@ class Num2WordsPTBRTest(TestCase):
self.n2w.to_currency(Decimal('1.01')), 'um real e um centavo'
)
self.assertEqual(
self.n2w.to_currency(Decimal('1.035')), 'um real e três centavos'
self.n2w.to_currency(Decimal('1.03')), 'um real e três centavos'
)
self.assertEqual(
self.n2w.to_currency(Decimal('1.35')),
'um real e trinta e cinco centavos'
)
self.assertEqual(
self.n2w.to_currency(Decimal('3.14159')),
self.n2w.to_currency(Decimal('3.14')),
'três reais e catorze centavos'
)
self.assertEqual(

View File

@@ -55,7 +55,7 @@ class Num2WordsDETest(TestCase):
self.assertEqual(num2words(4000000000, lang='sl'), "štiri miljarde")
def test_cardinal_for_decimal_number(self):
self.assertEqual(num2words(3.486, lang='sl'), "tri celih štiri osem")
self.assertEqual(num2words(3.48, lang='sl'), "tri celih štiri osem")
def test_ordinal_for_negative_numbers(self):
self.assertRaises(TypeError, num2words, -12, ordinal=True, lang='sl')