How do I convert a currency string to a floating point number in Python?

I have some strings representing numbers with specific currency format, for example:

money="$6,150,593.22"

I want to convert this string into the number

6150593.22

What is the best way to achieve this?

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

Try this:

from re import sub
from decimal import Decimal

money = '$6,150,593.22'
value = Decimal(sub(r'[^d.]', '', money))

This has some advantages since it uses Decimal instead of float (which is better for representing currency) and it also avoids any locale issues by not hard-coding a specific currency symbol.

Method 2

If your locale is set properly you can use locale.atof, but you will still need to strip off the ‘$’ manually:

>>> import locale
>>> locale.setlocale(locale.LC_ALL, 'en_US.UTF8')
'en_US.UTF8'
>>> money = "$6,150,593.22"
>>> locale.atof(money.strip("$"))
6150593.2199999997

Method 3

For a solution without hardcoding the currency position or symbol:

raw_price = "17,30 €"
import locale
locale.setlocale(locale.LC_ALL, 'fr_FR.UTF8')
conv = locale.localeconv()
raw_numbers = raw_price.strip(conv['currency_symbol'])
amount = locale.atof(raw_numbers)

Method 4

I found the babel package very helpful to work around

It makes it easy to parse a number in a localized rendition:

>>> babel.numbers.parse_decimal('1,024.64', locale='en')                                                                                                                           
Decimal('1024.64')
>>> babel.numbers.parse_decimal('1.024,64', locale='de')
Decimal('1024.64')
>>>

You can use babel.numbers.get_currency_symbol('USD') to strip pre/suffixes without hardcoding them.

Hth,
dtk

Method 5

Expanding to include negative numbers in parentheses:

In [1]: import locale, string

In [2]: from decimal import Decimal

In [3]: n = ['$1,234.56','-$1,234.56','($1,234.56)', '$ -1,234.56']

In [4]: tbl = string.maketrans('(','-')

In [5]: %timeit -n10000 [locale.atof( x.translate(tbl, '$)')) for x in n]
10000 loops, best of 3: 31.9 æs per loop

In [6]: %timeit -n10000 [Decimal( x.translate(tbl, '$,)')) for x in n]
10000 loops, best of 3: 21 æs per loop

In [7]: %timeit -n10000 [float( x.replace('(','-').translate(None, '$,)')) for x in n]
10000 loops, best of 3: 3.49 æs per loop

In [8]: %timeit -n10000 [float( x.translate(tbl, '$,)')) for x in n]
10000 loops, best of 3: 2.19 æs per loop

Note that commas must be stripped from float()/Decimal(). Either replace() or translate() w/ a translation table can be used to convert the opening ( to -, translate is slightly faster. float() is fastest by 10-15x, but lacks precision and could present locale issues. Decimal() has precision and is 50% faster than locale.atof(), but also has locale issues. locale.atof() is the slowest, but most general.

Edit: new str.translate API (characters mapped to None moved from str.translate function to the translation table)

In [1]: import locale, string
        from decimal import Decimal

        locale.setlocale(locale.LC_ALL, '')

        n = ['$1,234.56','-$1,234.56','($1,234.56)', '$ -1,234.56']

In [2]: tbl = str.maketrans('(', '-', '$)')
        %timeit -n10000 [locale.atof( x.translate(tbl)) for x in n]
18 µs ± 296 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

In [3]: tbl2 = str.maketrans('(', '-', '$,)')
        %timeit -n10000 [Decimal( x.translate(tbl2)) for x in n]
3.77 µs ± 50.8 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

In [4]: %timeit -n10000 [float( x.translate(tbl2)) for x in n]
3.13 µs ± 66.3 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

In [5]: tbl3 = str.maketrans('', '', '$,)')
        %timeit -n10000 [float( x.replace('(','-').translate(tbl3)) for x in n]
3.51 µs ± 84.8 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

Method 6

I made this function a few years ago to solve the same problem.

def money(number):
    number = number.strip('$')
    try:
        [num,dec]=number.rsplit('.')
        dec = int(dec)
        aside = str(dec)
        x = int('1'+'0'*len(aside))
        price = float(dec)/x
        num = num.replace(',','')
        num = int(num)
        price = num + price
    except:
        price = int(number)
    return price

Method 7

this function has convert turkish price format to decimal number.

money = '1.234,75'
def make_decimal(string):
    result = 0
    if string:
        [num, dec] = string.rsplit(',')
        result += int(num.replace('.', ''))
        result += (int(dec) / 100)
    return result
print(make_decimal(money))
1234.75

Method 8

Simplest way I found, without hard-coding on messing with currency detection, also uses the Decimal type which avoids issues with the float type:

>>> from decimal import Decimal
>>> money="$6,150,593.22"
>>> amount = Decimal("".join(d for d in money if d.isdigit() or d == '.'))
>>> amount
Decimal('6150593.22')

credit: https://www.reddit.com/r/learnpython/comments/2248mp/how_to_format_currency_without_currency_sign/cgjd1o4?utm_source=share&utm_medium=web2x

Method 9

I’ll provide my solution, hoping it would help someone who face problems with not just , but also ..

def process_currency_adaptive(currency_string: str, decimal_sep_char: str) -> float:
    """
    Converts the currency string to common float format:
        Format: 
            ######.### 
        Example: 
            6150593.22
    """
    # Get rid of currency symbol
    currency_symbols = ["$", "€", "£", "₺"]
    
    # Replace any occurrence of currency symbol with empty string
    for symbol in currency_symbols:
        currency_string = currency_string.replace(symbol, "")
    
    
    if decimal_sep_char == ",":
        triple_sep_char = "."
    elif decimal_sep_char == ".":
        triple_sep_char = ","
    else:
        raise ValueError("Invalid decimal separator character: {}".format(decimal_sep_char))

    # Get rid of the triple separator
    currency_string = currency_string.replace(triple_sep_char, "")
    
    # There should be only one decimal_sep_char.
    if currency_string.count(decimal_sep_char) != 1:
        print("Error: Invalid currency format with value: {}".format(currency_string))
        raise ValueError
    
    return float(currency_string.replace(decimal_sep_char, "."))

# test process_currency
print(process_currency_adaptive("942,695", decimal_sep_char=","))  # 942.695
print(process_currency_adaptive("$6,150,593.22", decimal_sep_char="."))  # 6150593.22        


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x