如何在 Python 中将带有点和逗号的字符串转换为浮点数
- 2024-12-17 08:30:00
- admin 原创
- 153
问题描述:
如何在 Python 中将字符串转换123,456.908
为浮点数?123456.908
对于int
s,请参阅如果字符串中包含逗号作为千位分隔符,如何将其转换为数字?,尽管技术本质上是相同的。
解决方案 1:
使用本地化服务
默认语言环境
标准库locale
模块是 Python 的基于 C 的本地化例程的接口。
基本用法是:
import locale
locale.atof('123,456')
,
在将其视为千位分隔符的区域设置中,它将返回123456.0
;在将其视为小数点的区域设置中,它将返回123.456
。
但是,默认情况下,这是行不通的:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python3.8/locale.py", line 326, in atof
return func(delocalize(string))
ValueError: could not convert string to float: '123,456'
这是因为默认情况下,程序“处于与代码运行平台无关的语言环境” ,而是由 POSIX 标准定义的。正如文档所解释的那样:
最初,当程序启动时,语言环境就是语言
C
环境,无论用户的首选语言环境是什么。有一个例外:类别LC_CTYPE
在启动时会更改,以将当前语言环境编码设置为用户的首选语言环境编码。程序必须通过调用 明确表示它希望其他类别使用用户的首选语言环境设置setlocale(LC_ALL, '')
。
也就是说:除了记下系统对文本文件中首选字符编码的默认设置(现在,这很可能是 UTF-8)之外,默认情况下,该locale
模块将以与 Python 本身相同的方式(通过以 C 编程语言命名的区域设置C
)解释数据。将执行与传递字符串locale.atof
相同的操作,并且同样会模仿。float
`locale.atoi`int
使用环境中的区域设置
执行setlocale
上述文档中引用的调用将从用户的环境中提取区域设置。因此:
>>> import locale
>>> # passing an empty string asks for a locale configured on the
>>> # local machine; the return value indicates what that locale is.
>>> locale.setlocale(locale.LC_ALL, '')
'en_CA.UTF-8'
>>> locale.atof('123,456.789')
123456.789
>>> locale.atof('123456.789')
123456.789
区域设置不会关心千位分隔符是否在正确的位置 - 它只是识别并过滤它们:
>>> locale.atof('12,34,56.789')
123456.789
在 3.6 及更高版本中,它也不会关心下划线,下划线由内置float
和int
转换单独处理:
>>> locale.atof('12_34_56.789')
123456.789
另一方面,如果使用以下格式,则字符串format
方法和 f 字符串可以识别语言环境n
:
>>> f'{123456.789:.9n}' # `.9` specifies 9 significant figures
'123,456.789'
如果没有之前的setlocale
调用,输出就不会有逗号。
明确设置语言环境
还可以使用适当的语言环境名称进行临时语言环境设置,并将这些设置仅应用于本地化的特定方面。例如,要获取仅针对数字的本地化解析和格式,请在调用中使用LC_NUMERIC
而不是。LC_ALL
`setlocale`
以下是一些示例:
>>> # in Denmark, periods are thousands separators and commas are decimal points
>>> locale.setlocale(locale.LC_NUMERIC, 'en_DK.UTF-8')
'en_DK.UTF-8'
>>> locale.atof('123,456.789')
123.456789
>>> # Formatting a number according to the Indian lakh/crore system:
>>> locale.setlocale(locale.LC_NUMERIC, 'en_IN.UTF-8')
'en_IN.UTF-8'
>>> f'{123456.789:9.9n}'
'1,23,456.789'
必要 的 语言 环境 字符串可能 取决于 您 的 操作系统, 并且可能 需要 额外 的 工作 才能 启用.
要恢复 Python 的默认行为,请使用C
前面描述的语言环境,如下所示:locale.setlocale(locale.LC_ALL, 'C')
。
注意事项
设置区域设置会影响程序的全局行为,并且不是线程安全的。如果要设置,通常应该在程序开始时只设置一次。再次引用文档:
调用某个库例程通常不是一个好主意
setlocale()
,因为它的副作用会影响整个程序。保存和恢复它几乎同样糟糕:它很昂贵,并且会影响在恢复设置之前运行的其他线程。
如果在编写通用模块时,您需要一个与区域设置无关的操作版本,而该操作会受到区域设置的影响(例如 使用的某些格式
time.strftime()
),则您必须找到一种不使用标准库例程的方法。更好的方法是说服自己使用区域设置是可以的。只有在万不得已的情况下,您才应该记录您的模块与非区域设置不兼容C
。
当 Python 代码嵌入 C 程序中时,设置区域设置甚至会影响 C 代码:
扩展模块永远不应该调用
setlocale()
,除非要找出当前的语言环境。但由于返回值只能用于恢复它,所以这不是很有用(除非可能要找出语言环境是否是C
)。
(注意:当setlocale
使用单个category
参数或非空None
字符串作为语言环境名称时,它不会改变任何内容,而只是返回现有语言环境的名称。)
因此,这并不是一个在生产代码中尝试解析或格式化针对不同语言环境的数据的工具。上述示例仅用于说明系统如何工作。为此,请寻找第三方国际化库。
但是,如果数据全部根据特定的语言环境进行格式化,则提前指定该语言环境将可以使用locale.atoi
和作为字符串输入的和调用的locale.atof
直接替代品。int
`float`
解决方案 2:
,
只需删除replace()
:
float("123,456.908".replace(',',''))
解决方案 3:
如果您不知道语言环境,但想要解析任何类型的数字,请使用此parseNumber(text)
函数(我的仓库)。它并不完美,但可以考虑大多数情况:
>>> parseNumber("a 125,00 €")
125
>>> parseNumber("100.000,000")
100000
>>> parseNumber("100 000,000")
100000
>>> parseNumber("100,000,000")
100000000
>>> parseNumber("100 000 000")
100000000
>>> parseNumber("100.001 001")
100.001
>>> parseNumber("$.3")
0.3
>>> parseNumber(".003")
0.003
>>> parseNumber(".003 55")
0.003
>>> parseNumber("3 005")
3005
>>> parseNumber("1.190,00 €")
1190
>>> parseNumber("1190,00 €")
1190
>>> parseNumber("1,190.00 €")
1190
>>> parseNumber("$1190.00")
1190
>>> parseNumber("$1 190.99")
1190.99
>>> parseNumber("1 000 000.3")
1000000.3
>>> parseNumber("1 0002,1.2")
10002.1
>>> parseNumber("")
>>> parseNumber(None)
>>> parseNumber(1)
1
>>> parseNumber(1.1)
1.1
>>> parseNumber("rrr1,.2o")
1
>>> parseNumber("rrr ,.o")
>>> parseNumber("rrr1rrr")
1
解决方案 4:
如果输入使用逗号作为小数点,使用句点作为千位分隔符,则使用.replace
两次将数据转换为内置使用的格式float
。因此:
s = s.replace('.','').replace(',','.')
number = float(s)
解决方案 5:
那这个呢?
my_string = "123,456.908"
commas_removed = my_string.replace(',', '') # remove comma separation
my_float = float(commas_removed) # turn from string to float.
简而言之:
my_float = float(my_string.replace(',', ''))
解决方案 6:
针对不同货币格式的更好解决方案:
def text_currency_to_float(text):
t = text
dot_pos = t.rfind('.')
comma_pos = t.rfind(',')
if comma_pos > dot_pos:
t = t.replace(".", "")
t = t.replace(",", ".")
else:
t = t.replace(",", "")
return float(t)
此函数通过检查逗号在字符串中从右侧开始的位置来检测逗号是否为千位分隔符或句号是否为小数分隔符。(前提是数字的小数部分不应使用千位分隔符。)
解决方案 7:
s = "123,456.908"
print float(s.replace(',', ''))
解决方案 8:
你可以使用 babel:
from babel.numbers import parse_decimal
f = float(parse_decimal("123,456.908", locale="en_US"))
解决方案 9:
这是我为您写的一个简单方法。:)
>>> number = '123,456,789.908'.replace(',', '') # '123456789.908'
>>> float(number)
123456789.908
解决方案 10:
这不是最短的解决方案,但为了完整性,如果您想依赖已经被证明一百万次的现有函数,这可能会很有趣:您可以通过将您的数字作为 StringIO 注入其函数来利用pandasread_csv()
(它有一个 C 后端,因此据我所知,转换功能不能直接利用)。
>>> float(pd.read_csv(StringIO("1,000.23"), sep=";", thousands=",", header=None)[0])
1000.23
特别是对于浮点数:如果您的数字使用点作为千位分隔符,使用逗号作为小数分隔符,decimal=","
那么除了设置之外,还要使用参数thousands="."
。