Skip to content

Commit

Permalink
add big numbers until Quintinillion
Browse files Browse the repository at this point in the history
add a test function for a big numbers
  • Loading branch information
hedhoud committed Mar 30, 2023
1 parent 8002ed4 commit 45a8d50
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 12 deletions.
39 changes: 29 additions & 10 deletions num2words/lang_AR.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@

class Num2Word_AR(Num2Word_Base):
errmsg_toobig = "abs(%s) must be less than %s."
MAXVAL = 1000000000000000050331649 # 10 **36
MAXVAL = 9999999999999999999999999999999999999999999999999 # 1000000000000000050331649 # 10 **36

This comment has been minimized.

Copy link
@Jeronymous

Jeronymous Mar 31, 2023

Contributor

@hedhoud this MAXVAL looks weird. What is the real value from which it fails to convert?
It should be something like 10 ** N

This comment has been minimized.

Copy link
@Jeronymous

Jeronymous Mar 31, 2023

Contributor

I checked : with what you added, the real MAXVAL is 10 ** 51.
And then you should check on 10 ** 51 - 1.
So add 2 unittests with these two values : MAXVAL (when it starts failing) and MAXVAL-1 (just before it fails)

Currently

In [1]: from num2words import num2words

In [2]: num2words(10**51 - 1, lang="ar")
Out[2]: 'تسعمائةتسعة و تسعون كوينتينيليوناً و تسعمائةتسعة و تسعون كوادريسيليوناً و تسعمائةتسعة و تسعون تريديسيليوناً و تسعمائةتسعة و تسعون دوديسيليوناً و تسعمائةتسعة و تسعون أندسيليوناً و تسعمائةتسعة و تسعون ديسيليوناً و تسعمائةتسعة و تسعون نونيليوناً و تسعمائةتسعة و تسعون أوكتيليوناً و تسعمائةتسعة و تسعون سبتيليوناً و تسعمائةتسعة و تسعون سكستيليوناً و تسعمائةتسعة و تسعون كوينتليوناً و تسعمائةتسعة و تسعون كوادريليوناً و تسعمائةتسعة و تسعون تريليوناً و تسعمائةتسعة و تسعون ملياراً و تسعمائةتسعة و تسعون مليوناً و تسعمائةتسعة و تسعون ألفاً و تسعمائةتسعة و تسعون'

When I translate that output to English (with google translate) I get a different results than num2words(10**51 - 1, lang="en").
Below, left is the translation of the current Arabic conversion by num2words (for 10**51 - 1), right is English conversion by num2words:
image
The differences might just be due to google translate being wrong.
But the parts where it differs deserve to be double checked.

Note: I removed the "and" and the commas in the above comparaison, so all the "و" should be double-checked in the output for MAXVAL-1


def __init__(self):
super().__init__()
Expand Down Expand Up @@ -79,26 +79,37 @@ def __init__(self):
self.arabicHundreds = [
"", "مائة", "مئتان", "ثلاثمائة", "أربعمائة", "خمسمائة", "ستمائة",
"سبعمائة", "ثمانمائة", "تسعمائة"
]
] # should be : ["تسعة مائة","ثمانية مائة","سبعة مائة","ستة مائة","خمسة مائة","أربعة مائة","ثلاثة مائة","مئتان","مائة"]

self.arabicAppendedTwos = [
"مئتا", "ألفا", "مليونا", "مليارا", "تريليونا", "كوادريليونا",
"كوينتليونا", "سكستيليونا"
"كوينتليونا", "سكستيليونا","سبتيليونا","أوكتيليونا ","نونيليونا",
"ديسيليونا","أندسيليونا","دوديسيليونا","تريديسيليونا","كوادريسيليونا",
"كوينتينيليونا"
]
self.arabicTwos = [
"مئتان", "ألفان", "مليونان", "ملياران", "تريليونان",
"كوادريليونان", "كوينتليونان", "سكستيليونان"
"كوادريليونان", "كوينتليونان", "سكستيليونان","سبتيليونان",
"أوكتيليونان ","نونيليونان ","ديسيليونان","أندسيليونان",
"دوديسيليونان","تريديسيليونان","كوادريسيليونان","كوينتينيليونان"
]
self.arabicGroup = [
"مائة", "ألف", "مليون", "مليار", "تريليون", "كوادريليون",
"كوينتليون", "سكستيليون"
"كوينتليون", "سكستيليون","سبتيليون","أوكتيليون","نونيليون",
"ديسيليون","أندسيليون","دوديسيليون","تريديسيليون","كوادريسيليون",
"كوينتينيليون"
]
self.arabicAppendedGroup = [
"", "ألفاً", "مليوناً", "ملياراً", "تريليوناً", "كوادريليوناً",
"كوينتليوناً", "سكستيليوناً"
"كوينتليوناً", "سكستيليوناً","سبتيليوناً","أوكتيليوناً","نونيليوناً",
"ديسيليوناً","أندسيليوناً","دوديسيليوناً","تريديسيليوناً","كوادريسيليوناً",
"كوينتينيليوناً"
]
self.arabicPluralGroups = [
"", "آلاف", "ملايين", "مليارات", "تريليونات", "كوادريليونات",
"كوينتليونات", "سكستيليونات"
"كوينتليونات", "سكستيليونات","سبتيليونات","أوكتيليونات","نونيليونات",
"ديسيليونات","أندسيليونات","دوديسيليونات","تريديسيليونات","كوادريسيليونات",
"كوينتينيليونات"
]
assert len(self.arabicAppendedGroup) == len(self.arabicGroup)
assert len(self.arabicPluralGroups) == len(self.arabicGroup)
Expand Down Expand Up @@ -209,8 +220,16 @@ def process_arabic_group(self, group_number, group_level,

return ret_val

def abs(self, number):
return number if number >= 0 else -number

def to_str(self, number):
integer = int(number)
decimal = round((number - integer) * 10**9)
return str(integer) + "." + "{:09d}".format(decimal)

def convert(self, value):
self.number = "{:.9f}".format(value)
self.number = self.to_str(value)
self.number_to_arabic(self.arabicPrefixText, self.arabicSuffixText)
return self.convert_to_arabic()

Expand Down Expand Up @@ -346,7 +365,7 @@ def to_ordinal(self, number, prefix=''):
self.currency_unit = ('', '', '', '')
self.arabicPrefixText = prefix
self.arabicSuffixText = ""
return "{}".format(self.convert(abs(number)).strip())
return "{}".format(self.convert(self.abs(number)).strip())

def to_year(self, value):
value = self.validate_number(value)
Expand All @@ -367,4 +386,4 @@ def to_cardinal(self, number):
self.arabicPrefixText = ""
self.arabicSuffixText = ""
self.arabicOnes = ARABIC_ONES
return minus + self.convert(value=abs(number)).strip()
return minus + self.convert(value=self.abs(number)).strip()
15 changes: 13 additions & 2 deletions tests/test_ar.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,9 +132,20 @@ def test_year(self):

def test_max_numbers(self):

for number in 10 ** 36, 123456789123456789123456789, 123456789123456789123456789123456789:

for number in 9999999999999999999999999999999999999999999999999, 10000000000000000000000000000000000000000000000000:

This comment has been minimized.

Copy link
@Jeronymous

Jeronymous Mar 31, 2023

Contributor

@hedhoud Use 10 ** N, 10 ** N - 1, ... so that it's more readable

with self.assertRaises(OverflowError) as context:
num2words(number, lang='ar')

self.assertTrue('must be less' in str(context.exception))

def test_big_numbers(self):
self.assertEqual(num2words(1000000045000000000000003000000002000000300, to='cardinal', lang='ar'),
'واحد تريديسيليون و خمسة و أربعون ديسيليوناً و ثلاثة كوينتليونات و ملياران و ثلاثمائة'
)
self.assertEqual(num2words(-1000000000000000000000003000000002000000302, to='cardinal', lang='ar'),
'سالب واحد تريديسيليون و ثلاثة كوينتليونات و ملياران و ثلاثمائة و اثنان'
)
self.assertEqual(num2words(9999999999999999999999999999999999999999999999992, to='cardinal', lang='ar'),
'تسعة كوينتينيليونات و تسعمائةتسعة و تسعون كوادريسيليوناً و تسعمائةتسعة و تسعون تريديسيليوناً و تسعمائةتسعة و تسعون دوديسيليوناً و تسعمائةتسعة و تسعون أندسيليوناً و تسعمائةتسعة و تسعون ديسيليوناً و تسعمائةتسعة و تسعون نونيليوناً و تسعمائةتسعة و تسعون أوكتيليوناً و تسعمائةتسعة و تسعون سبتيليوناً و تسعمائةتسعة و تسعون سكستيليوناً و تسعمائةتسعة و تسعون كوينتليوناً و تسعمائةتسعة و تسعون كوادريليوناً و تسعمائةتسعة و تسعون تريليوناً و تسعمائةتسعة و تسعون ملياراً و تسعمائةتسعة و تسعون مليوناً و تسعمائةتسعة و تسعون ألفاً و تسعمائةاثنان و تسعون'
)

0 comments on commit 45a8d50

Please sign in to comment.