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

Asked By: User_Targaryen

||

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.

Answered By: Adam Starrh

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
Answered By: navule

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)

Answered By: Vanjith
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
Answered By: Piyush Kumar

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 ₹        
Answered By: Ganesh Murugan
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
Answered By: pgksunilkumar

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
Answered By: Mian
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.