Convert an amount to Indian Notation in Python
Question:
Problem: I need to convert an amount to Indian currency format
My code: I have the following Python
implementation:
import decimal
def currencyInIndiaFormat(n):
d = decimal.Decimal(str(n))
if d.as_tuple().exponent < -2:
s = str(n)
else:
s = '{0:.2f}'.format(n)
l = len(s)
i = l-1;
res = ''
flag = 0
k = 0
while i>=0:
if flag==0:
res = res + s[i]
if s[i]=='.':
flag = 1
elif flag==1:
k = k + 1
res = res + s[i]
if k==3 and i-1>=0:
res = res + ','
flag = 2
k = 0
else:
k = k + 1
res = res + s[i]
if k==2 and i-1>=0:
res = res + ','
flag = 2
k = 0
i = i - 1
return res[::-1]
def main():
n = 100.52
print "INR " + currencyInIndiaFormat(n) # INR 100.52
n = 1000.108
print "INR " + currencyInIndiaFormat(n) # INR 1,000.108
n = 1200000
print "INR " + currencyInIndiaFormat(n) # INR 12,00,000.00
main()
My Question: Is there a way to make my currencyInIndiaFormat function shorter, more concise and clean ? / Is there a better way to write my currencyInIndiaFormat function ?
Note: My question is mainly based on Python
implementation of the above stated problem. It is not a duplicate of previously asked questions regarding conversion of currency to Indian format.
Indian Currency Format:
For example, numbers here are represented as:
1
10
100
1,000
10,000
1,00,000
10,00,000
1,00,00,000
10,00,00,000
Refer Indian Numbering System
Answers:
Too much work.
>>> import locale
>>> locale.setlocale(locale.LC_MONETARY, 'en_IN')
'en_IN'
>>> print(locale.currency(100.52, grouping=True))
₹ 100.52
>>> print(locale.currency(1000.108, grouping=True))
₹ 1,000.11
>>> print(locale.currency(1200000, grouping=True))
₹ 12,00,000.00
Couldn’t make the other two solutions work for me, so I made something a little more low-tech:
def format_as_indian(input):
input_list = list(str(input))
if len(input_list) <= 1:
formatted_input = input
else:
first_number = input_list.pop(0)
last_number = input_list.pop()
formatted_input = first_number + (
(''.join(l + ',' * (n % 2 == 1) for n, l in enumerate(reversed(input_list)))[::-1] + last_number)
)
if len(input_list) % 2 == 0:
formatted_input.lstrip(',')
return formatted_input
This doesn’t work with decimals. If you need that, I would suggest saving the decimal portion into another variable and adding it back in at the end.
You can follow these steps.
Install Babel python package from pip
pip install Babel
In your python script
from babel.numbers import format_currency
format_currency(5433422.8012, 'INR', locale='en_IN')
Output:
₹ 54,33,422.80
Here is the other way around:
import re
def in_for(value):
value,b=str(value),''
value=''.join(map(lambda va:va if re.match(r'[0-9,.]',va) else '',value))
val=value
if val.count(',')==0:
v,c,a,cc,ii=val,0,[3,2,2],0,0
val=val[:val.rfind('.')] if val.rfind('.')>=0 else val
for i in val[::-1]:
if c==ii and c!=0:
ii+=a[cc%3]
b=','+i+b
cc+=1
else:
b=i+b
c+=1
b=b[1:] if b[0]==',' else b
val=b+v[value.rfind('.'):] if value.rfind('.')>=0 else b
else:
val=str(val).strip('()').replace(' ','')
v=val.rfind('.')
if v>0:
val=val[:v+3]
return val.rstrip('0').rstrip('.') if '.' in val else val
print(in_for('1000000000000.5445'))
Output will be:
10,000,00,00,000.54
(As mentioned in wikipedia indian number system Ex:67,89,000,00,00,000)
def format_indian(t):
dic = {
4:'Thousand',
5:'Lakh',
6:'Lakh',
7:'Crore',
8:'Crore',
9:'Arab'
}
y = 10
len_of_number = len(str(t))
save = t
z=y
while(t!=0):
t=int(t/y)
z*=10
zeros = len(str(z)) - 3
if zeros>3:
if zeros%2!=0:
string = str(save)+": "+str(save/(z/100))[0:4]+" "+dic[zeros]
else:
string = str(save)+": "+str(save/(z/1000))[0:4]+" "+dic[zeros]
return string
return str(save)+": "+str(save)
This code will Convert Yout Numbers to Lakhs, Crores and arabs in most simplest way. Hope it helps.
for i in [1.234567899 * 10**x for x in range(9)]:
print(format_indian(int(i)))
Output:
1: 1
12: 12
123: 123
1234: 1234
12345: 12.3 Thousand
123456: 1.23 Lakh
1234567: 12.3 Lakh
12345678: 1.23 Crore
123456789: 12.3 Crore
Another way:
def formatted_int(value):
# if the value is 100, 10, 1
if len(str(value)) <= 3:
return value
# if the value is 10,000, 1,000
elif 3 < len(str(value)) <= 5:
return f'{str(value)[:-3]},{str(value)[-3:]} ₹'
# if the value is greater the 10,000
else:
cut = str(value)[:-3]
o = []
while cut:
o.append(cut[-2:]) # appending from 1000th value(right to left)
cut = cut[:-2]
o = o[::-1] # reversing list
res = ",".join(o)
return f'{res},{str(value)[-3:]} ₹'
value1 = 1_00_00_00_000
value2 = 10_00_00_00_000
value3 = 100
print(formatted_int(value1))
print(formatted_int(value2))
print(formatted_int(value3))
Ouput:
1,00,00,00,000 ₹
10,00,00,00,000 ₹
100 ₹
num=123456789
snum=str(num)
slen=len(snum)
result=''
if (slen-3)%2 !=0 :
snum='x'+snum
for i in range(0,slen-3,2):
result=result+snum[i:i+2]+','
result+=snum[slen-3:]
print(result.replace('x',''))
def formatINR(number):
s, *d = str(number).partition(".")
r = ",".join([s[x-2:x] for x in range(-3, -len(s), -2)][::-1] + [s[-3:]])
return "".join([r] + d)
It’s simple to use:
print(formatINR(123456))
Output
1,23,456
If you want to handle negative numbers
def negativeFormatINR(number):
negativeNumber = False
if number < 0:
number = abs(number)
negativeNumber = True
s, *d = str(number).partition(".")
r = ",".join([s[x-2:x] for x in range(-3, -len(s), -2)][::-1] + [s[-3:]])
value = "".join([r] + d)
if negativeNumber:
return '-' + value
return value
It’s simple to use:
print(negativeFormatINR(100-10000))
output
-9,900
Note – THIS IS AN ALTERNATIVE SOLUTION FOR ACTUAL QUESTION
If anyone trying to convert in simple Indian terms like K
, L
, or Cr
with 2 floating-point values, the following solution would work.
def format_cash(amount):
def truncate_float(number, places):
return int(number * (10 ** places)) / 10 ** places
if amount < 1e3:
return amount
if 1e3 <= amount < 1e5:
return str(truncate_float((amount / 1e5) * 100, 2)) + " K"
if 1e5 <= amount < 1e7:
return str(truncate_float((amount / 1e7) * 100, 2)) + " L"
if amount > 1e7:
return str(truncate_float(amount / 1e7, 2)) + " Cr"
Examples
format_cash(7843) --> '7.84 K'
format_cash(78436) --> '78.43 K'
format_cash(784367) --> '7.84 L'
format_cash(7843678) --> '78.43 L'
format_cash(78436789) --> '7.84 Cr'
As pgksunilkumar’s answer, a little improvement is done in case the the number is in between 0 to -1000
def formatINR(number):
if number < 0 and number > -1000:
return number
else:
s, *d = str(number).partition(".")
r = ",".join([s[x-2:x] for x in range(-3, -len(s), -2)][::-1] + [s[-3:]])
return "".join([r] + d)
now if the number is between 0 to -1000, the format will not disturb the user.
i.e
a = -600
b = -10000000
c = 700
d = 8000000
print(formatINR(a))
print(formatINR(b))
print(formatINR(c))
print(formatINR(d))
output will be:
-600
-1,00,00,000
700
80,00,000
Problem: I need to convert an amount to Indian currency format
My code: I have the following Python
implementation:
import decimal
def currencyInIndiaFormat(n):
d = decimal.Decimal(str(n))
if d.as_tuple().exponent < -2:
s = str(n)
else:
s = '{0:.2f}'.format(n)
l = len(s)
i = l-1;
res = ''
flag = 0
k = 0
while i>=0:
if flag==0:
res = res + s[i]
if s[i]=='.':
flag = 1
elif flag==1:
k = k + 1
res = res + s[i]
if k==3 and i-1>=0:
res = res + ','
flag = 2
k = 0
else:
k = k + 1
res = res + s[i]
if k==2 and i-1>=0:
res = res + ','
flag = 2
k = 0
i = i - 1
return res[::-1]
def main():
n = 100.52
print "INR " + currencyInIndiaFormat(n) # INR 100.52
n = 1000.108
print "INR " + currencyInIndiaFormat(n) # INR 1,000.108
n = 1200000
print "INR " + currencyInIndiaFormat(n) # INR 12,00,000.00
main()
My Question: Is there a way to make my currencyInIndiaFormat function shorter, more concise and clean ? / Is there a better way to write my currencyInIndiaFormat function ?
Note: My question is mainly based on Python
implementation of the above stated problem. It is not a duplicate of previously asked questions regarding conversion of currency to Indian format.
Indian Currency Format:
For example, numbers here are represented as:
1
10
100
1,000
10,000
1,00,000
10,00,000
1,00,00,000
10,00,00,000
Refer Indian Numbering System
Too much work.
>>> import locale
>>> locale.setlocale(locale.LC_MONETARY, 'en_IN')
'en_IN'
>>> print(locale.currency(100.52, grouping=True))
₹ 100.52
>>> print(locale.currency(1000.108, grouping=True))
₹ 1,000.11
>>> print(locale.currency(1200000, grouping=True))
₹ 12,00,000.00
Couldn’t make the other two solutions work for me, so I made something a little more low-tech:
def format_as_indian(input):
input_list = list(str(input))
if len(input_list) <= 1:
formatted_input = input
else:
first_number = input_list.pop(0)
last_number = input_list.pop()
formatted_input = first_number + (
(''.join(l + ',' * (n % 2 == 1) for n, l in enumerate(reversed(input_list)))[::-1] + last_number)
)
if len(input_list) % 2 == 0:
formatted_input.lstrip(',')
return formatted_input
This doesn’t work with decimals. If you need that, I would suggest saving the decimal portion into another variable and adding it back in at the end.
You can follow these steps.
Install Babel python package from pip
pip install Babel
In your python script
from babel.numbers import format_currency
format_currency(5433422.8012, 'INR', locale='en_IN')
Output:
₹ 54,33,422.80
Here is the other way around:
import re
def in_for(value):
value,b=str(value),''
value=''.join(map(lambda va:va if re.match(r'[0-9,.]',va) else '',value))
val=value
if val.count(',')==0:
v,c,a,cc,ii=val,0,[3,2,2],0,0
val=val[:val.rfind('.')] if val.rfind('.')>=0 else val
for i in val[::-1]:
if c==ii and c!=0:
ii+=a[cc%3]
b=','+i+b
cc+=1
else:
b=i+b
c+=1
b=b[1:] if b[0]==',' else b
val=b+v[value.rfind('.'):] if value.rfind('.')>=0 else b
else:
val=str(val).strip('()').replace(' ','')
v=val.rfind('.')
if v>0:
val=val[:v+3]
return val.rstrip('0').rstrip('.') if '.' in val else val
print(in_for('1000000000000.5445'))
Output will be:
10,000,00,00,000.54
(As mentioned in wikipedia indian number system Ex:67,89,000,00,00,000)
def format_indian(t):
dic = {
4:'Thousand',
5:'Lakh',
6:'Lakh',
7:'Crore',
8:'Crore',
9:'Arab'
}
y = 10
len_of_number = len(str(t))
save = t
z=y
while(t!=0):
t=int(t/y)
z*=10
zeros = len(str(z)) - 3
if zeros>3:
if zeros%2!=0:
string = str(save)+": "+str(save/(z/100))[0:4]+" "+dic[zeros]
else:
string = str(save)+": "+str(save/(z/1000))[0:4]+" "+dic[zeros]
return string
return str(save)+": "+str(save)
This code will Convert Yout Numbers to Lakhs, Crores and arabs in most simplest way. Hope it helps.
for i in [1.234567899 * 10**x for x in range(9)]:
print(format_indian(int(i)))
Output:
1: 1
12: 12
123: 123
1234: 1234
12345: 12.3 Thousand
123456: 1.23 Lakh
1234567: 12.3 Lakh
12345678: 1.23 Crore
123456789: 12.3 Crore
Another way:
def formatted_int(value):
# if the value is 100, 10, 1
if len(str(value)) <= 3:
return value
# if the value is 10,000, 1,000
elif 3 < len(str(value)) <= 5:
return f'{str(value)[:-3]},{str(value)[-3:]} ₹'
# if the value is greater the 10,000
else:
cut = str(value)[:-3]
o = []
while cut:
o.append(cut[-2:]) # appending from 1000th value(right to left)
cut = cut[:-2]
o = o[::-1] # reversing list
res = ",".join(o)
return f'{res},{str(value)[-3:]} ₹'
value1 = 1_00_00_00_000
value2 = 10_00_00_00_000
value3 = 100
print(formatted_int(value1))
print(formatted_int(value2))
print(formatted_int(value3))
Ouput:
1,00,00,00,000 ₹
10,00,00,00,000 ₹
100 ₹
num=123456789
snum=str(num)
slen=len(snum)
result=''
if (slen-3)%2 !=0 :
snum='x'+snum
for i in range(0,slen-3,2):
result=result+snum[i:i+2]+','
result+=snum[slen-3:]
print(result.replace('x',''))
def formatINR(number):
s, *d = str(number).partition(".")
r = ",".join([s[x-2:x] for x in range(-3, -len(s), -2)][::-1] + [s[-3:]])
return "".join([r] + d)
It’s simple to use:
print(formatINR(123456))
Output
1,23,456
If you want to handle negative numbers
def negativeFormatINR(number):
negativeNumber = False
if number < 0:
number = abs(number)
negativeNumber = True
s, *d = str(number).partition(".")
r = ",".join([s[x-2:x] for x in range(-3, -len(s), -2)][::-1] + [s[-3:]])
value = "".join([r] + d)
if negativeNumber:
return '-' + value
return value
It’s simple to use:
print(negativeFormatINR(100-10000))
output
-9,900
Note – THIS IS AN ALTERNATIVE SOLUTION FOR ACTUAL QUESTION
If anyone trying to convert in simple Indian terms like K
, L
, or Cr
with 2 floating-point values, the following solution would work.
def format_cash(amount):
def truncate_float(number, places):
return int(number * (10 ** places)) / 10 ** places
if amount < 1e3:
return amount
if 1e3 <= amount < 1e5:
return str(truncate_float((amount / 1e5) * 100, 2)) + " K"
if 1e5 <= amount < 1e7:
return str(truncate_float((amount / 1e7) * 100, 2)) + " L"
if amount > 1e7:
return str(truncate_float(amount / 1e7, 2)) + " Cr"
Examples
format_cash(7843) --> '7.84 K'
format_cash(78436) --> '78.43 K'
format_cash(784367) --> '7.84 L'
format_cash(7843678) --> '78.43 L'
format_cash(78436789) --> '7.84 Cr'
As pgksunilkumar’s answer, a little improvement is done in case the the number is in between 0 to -1000
def formatINR(number):
if number < 0 and number > -1000:
return number
else:
s, *d = str(number).partition(".")
r = ",".join([s[x-2:x] for x in range(-3, -len(s), -2)][::-1] + [s[-3:]])
return "".join([r] + d)
now if the number is between 0 to -1000, the format will not disturb the user.
i.e
a = -600
b = -10000000
c = 700
d = 8000000
print(formatINR(a))
print(formatINR(b))
print(formatINR(c))
print(formatINR(d))
output will be:
-600
-1,00,00,000
700
80,00,000