Подтвердить что ты не робот

Как преобразовать строку валюты в число с плавающей запятой в Python?

У меня есть несколько строк, представляющих числа с определенным валютным форматом, например:

money="$6,150,593.22"

Я хочу преобразовать эту строку в число

6150593.22

Каков наилучший способ достичь этого?

4b9b3361

Ответ 1

Попробуйте следующее:

from re import sub
from decimal import Decimal

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

У этого есть некоторые преимущества, поскольку он использует Decimal вместо float (что лучше для представления валюты), а также избегает любых проблем с локальностью, -кодирование определенного символа валюты.

Ответ 2

Если ваш языковой стандарт установлен правильно, вы можете использовать locale.atof, но вам все равно придется вручную отключить '$':

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

Ответ 3

Расширение для включения отрицательных чисел в скобки:

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

Обратите внимание, что запятые должны быть удалены из float()/Decimal(). Либо replace(), либо translate() с таблицей перевода можно использовать для преобразования открытия (в -, переводить немного быстрее. Float() быстрее всего в 10-15 раз, но ему не хватает точности и могут возникнуть проблемы с локалью. Decimal ( ) имеет точность и на 50% быстрее, чем locale.atof(), но также имеет проблемы с локалью. locale.atof() - самый медленный, но самый общий.

Изменение: новый API-интерфейс str.translate

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)

Ответ 4

Для решения без жесткого кодирования позиция или символ валюты:

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'].decode('utf-8'))
amount = locale.atof(raw_numbers)

Ответ 5

Я нашел пакет babel очень полезным для обхода

Это позволяет легко разобрать число в локализованном представлении:

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

Вы можете использовать babel.numbers.get_currency_symbol('USD') чтобы удалить пре/суффиксы без их babel.numbers.get_currency_symbol('USD').

Hth, DTK

Ответ 6

Я сделал эту функцию несколько лет назад, чтобы решить ту же проблему.

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