Python 将百分比数字表示形式转换为浮点数
Python convert percentage number representations to float
在 python 中是否有一种简单的方法可以将字符串表示形式(例如“50%”)转换为浮点数?我在 yaml 中有数据并正在解析它。我想支持“0.5”和“50%”作为有效表示。因此,仅剥离 "%" 是不够的。
您可以使用以下方法转换字符串:
a = "40.3%"
b = float(a[:-1])/100
怎么样:
def parseFloat(str):
try:
return float(str)
except:
str = str.strip()
if str.endswith("%"):
return float(str.strip("%").strip()) / 100
raise Exception("Don't know how to parse %s" % str)
print(parseFloat("50%"))
print(parseFloat("0.5"))
该代码甚至支持解析如下所示的字符串:
print(parseFloat(" 50 % "))
YAML 中任何以百分号结尾的数字序列,都将
通常作为字符串标量加载,因为 %
不会
标量匹配任何其他模式(特别是不是整数
或浮动)。您当然可以递归遍历数据结构
从 YAML 加载并打补丁,但是如果
数据结构,用于构造特定对象,递归到那些
至少是不平凡的,如果不是不可能的话。
最好的解决方案是您的 YAML 明确
通过标签说明什么是百分比。例如:
a: !Percentage 60%
,其中从该标记加载的对象的行为类似于浮动
0.6。但是在使用 YAML 时标签没有得到充分利用,而您却没有
表示您的输入是以这种方式标记的。
幸运的是,为百分比设置解析器并不太难
在加载程序中,在下文中我将针对默认值 RoundTripLoader
.
执行此操作
待解析的YAML文档in.yaml
:
%YAML 1.2
---
a: 60.3%
42%: 'abc'
您可以连接到字符串的表示器以检查它们是否由数字组成
并以百分号结尾,但添加解析器会更快:
import sys
import re
from pathlib import Path
import ruamel.yaml
from ruamel.yaml.util import RegExp
ruamel.yaml.resolver.VersionedResolver.add_implicit_resolver(
u'percentage',
RegExp(u'''^(?:[-+]?[0-9_]+%
|[-+]?(?:[0-9][0-9_]*)\.[0-9_]*(?:[eE][-+]?[0-9]+)?%
)$''', re.X
),
list(u'-+0123456789.'))
def construct_percentage(self, node):
value = float(node.value[:-1]) / 100.0
return value
ruamel.yaml.constructor.RoundTripConstructor.add_constructor(
u'percentage', construct_percentage
)
yaml = ruamel.yaml.YAML()
data = yaml.load(Path('in.yaml'))
print(dict(data))
给出:
{'a': 0.603, 0.42: 'abc'}
请注意:
- 默认情况下,数据加载到
ordereddict
的子类中,因此调用 dict()
。
- 如果你还想转储百分比,你应该将它们加载为 float 的子类,
因此,当您要转储它们时,它们可以与普通浮动区分开来。
- 我故意遗漏了
int
的附加格式(十六进制、八进制等)和
浮点数(科学计数法、NaN 等)。他们在我看来没有多大意义,但他们
可以通过模式匹配器重新允许。
在 python 中是否有一种简单的方法可以将字符串表示形式(例如“50%”)转换为浮点数?我在 yaml 中有数据并正在解析它。我想支持“0.5”和“50%”作为有效表示。因此,仅剥离 "%" 是不够的。
您可以使用以下方法转换字符串:
a = "40.3%"
b = float(a[:-1])/100
怎么样:
def parseFloat(str):
try:
return float(str)
except:
str = str.strip()
if str.endswith("%"):
return float(str.strip("%").strip()) / 100
raise Exception("Don't know how to parse %s" % str)
print(parseFloat("50%"))
print(parseFloat("0.5"))
该代码甚至支持解析如下所示的字符串:
print(parseFloat(" 50 % "))
YAML 中任何以百分号结尾的数字序列,都将
通常作为字符串标量加载,因为 %
不会
标量匹配任何其他模式(特别是不是整数
或浮动)。您当然可以递归遍历数据结构
从 YAML 加载并打补丁,但是如果
数据结构,用于构造特定对象,递归到那些
至少是不平凡的,如果不是不可能的话。
最好的解决方案是您的 YAML 明确 通过标签说明什么是百分比。例如:
a: !Percentage 60%
,其中从该标记加载的对象的行为类似于浮动 0.6。但是在使用 YAML 时标签没有得到充分利用,而您却没有 表示您的输入是以这种方式标记的。
幸运的是,为百分比设置解析器并不太难
在加载程序中,在下文中我将针对默认值 RoundTripLoader
.
待解析的YAML文档in.yaml
:
%YAML 1.2
---
a: 60.3%
42%: 'abc'
您可以连接到字符串的表示器以检查它们是否由数字组成 并以百分号结尾,但添加解析器会更快:
import sys
import re
from pathlib import Path
import ruamel.yaml
from ruamel.yaml.util import RegExp
ruamel.yaml.resolver.VersionedResolver.add_implicit_resolver(
u'percentage',
RegExp(u'''^(?:[-+]?[0-9_]+%
|[-+]?(?:[0-9][0-9_]*)\.[0-9_]*(?:[eE][-+]?[0-9]+)?%
)$''', re.X
),
list(u'-+0123456789.'))
def construct_percentage(self, node):
value = float(node.value[:-1]) / 100.0
return value
ruamel.yaml.constructor.RoundTripConstructor.add_constructor(
u'percentage', construct_percentage
)
yaml = ruamel.yaml.YAML()
data = yaml.load(Path('in.yaml'))
print(dict(data))
给出:
{'a': 0.603, 0.42: 'abc'}
请注意:
- 默认情况下,数据加载到
ordereddict
的子类中,因此调用dict()
。 - 如果你还想转储百分比,你应该将它们加载为 float 的子类, 因此,当您要转储它们时,它们可以与普通浮动区分开来。
- 我故意遗漏了
int
的附加格式(十六进制、八进制等)和 浮点数(科学计数法、NaN 等)。他们在我看来没有多大意义,但他们 可以通过模式匹配器重新允许。