将输入从非整数比特率转换成可行的值

时间:2018-11-14 22:24:11

标签: python

我有一个程序,其输入已更改。它最初使用整数时有效,并且整数的单位如下:“ kbps”,“ Mbps”,“ Gbps”。一个例子:

10kbps
20Mbps
20Gbps

我使用“ if / then”将所有字符串转换为bps:

if "kbps" in bandwidth:
    bw=bandwidth.replace('kbps', '000')
elif "Mbps" in bandwidth:
    bw=bandwidth.replace('Mbps', '000000')
elif "Gbps" in bandwidth:
    bw=bandwidth.replace('Gbps', '000000000')
else:
    bw='0'

我将“ bw”打印为整数“ int(bw)”,并且工作正常。现在,输入已更改。这是实际输入的示例:

3.838Mbps
100kbps
126.533kbps
5.23Mbps
100Mbps
1.7065Gbps
20Gbps

数字不是整数。因为它不是整数,所以我不仅不能打印,而且单位转换不能与小数一起使用。例如,3.838Mbps变为3.838000000。

有人可以建议使用这些输入的有效方法吗?我找不到分割,正则表达式匹配等的正确平衡,并且想知道是否有一些我不知道的方法。

4 个答案:

答案 0 :(得分:4)

我会做类似的事情:

import re

UNITS = {
    'k': 1e3,
    'm': 1e6,
    'g': 1e9,
    't': 1e12,
}

def parse_bps(s):
    m = re.match(r'^([0-9]+(\.[0-9]*)?)([tgmk])?bps$', s, re.IGNORECASE)
    if not m:
        raise ValueError(f"unsupported value for parse_bps: {repr(s)}")
    val = float(m.group(1))
    unit = m.group(3)
    if unit:
        val *= UNITS[unit.lower()]
    return val


tests = [
    '10bps', '10kbps', '20Mbps', '20Gbps', '3.838Mbps',
    '3.838Mbps', '100kbps', '126.533kbps', '5.23Mbps',
    '100Mbps', '1.7065Gbps', '20Gbps',
]

for s in tests:
    print(f'  {repr(s)} = {parse_bps(s)}')

尽管最好不要忽略大小写。 SI units正式根据大小写产生很大的差异,通常来说,大写字母表示乘法,小写字母表示除法。

答案 1 :(得分:4)

我认为在这里使用正则表达式并捕获“数字部分”和“单元前缀部分”可能会更好:

import re

bandwidth_rgx = re.compile(r'^(\d*(?:\.\d*)?)\s*([GMk]?)(?:bps)?$')

所以现在我们可以匹配给定的字符串,并获得数字部分和单位前缀部分:

>>> bandwidth_rgx.search('126.533kbps')[1]
'126.533'
>>> bandwidth_rgx.search('126.533kbps')[2]
'k'

所以我们可以制作一个转换字典,例如:

unit_prefix = {
    '': 1,
    'k': 1000,
    'M': 1000000,
    'G': 1000000000
}

并使用一个函数来获取带宽,例如作为浮点数:

def get_bandwidth(text):
    m = bandwidth_rgx.search(text)
    return float(m[1]) * unit_prefix[m[2]]

例如:

>>> get_bandwidth('3.838Mbps')
3838000.0
>>> get_bandwidth('100kbps')
100000.0
>>> get_bandwidth('126.533kbps')
126533.0
>>> get_bandwidth('5.23Mbps')
5230000.0
>>> get_bandwidth('100Mbps')
100000000.0
>>> get_bandwidth('1.7065Gbps')
1706500000.0
>>> get_bandwidth('20Gbps')
20000000000.0

答案 2 :(得分:4)

您可以在kbpsMbpsGbps之前强制转换值以进行浮动,然后乘以1000、1000,000等。无论哪种情况都可以。

例如:

if "kbps" in bandwidth:
    bw = bandwidth.replace('kbps', '')
    bw = str(float(bw) * 1000)
elif "Mbps" in bandwidth:
    bw = bandwidth.replace('Mbps', '')
    bw = str(float(bw) * 1000* 1000)
elif "Gbps" in bandwidth:
    bw = bandwidth.replace('Gbps', '')
    bw = str(float(bw) * 1000 * 1000 * 1000)
else:
    bw='0'

答案 3 :(得分:1)

需要最少的代码更改并假设您的输入是安全的答案:

if "kbps" in bandwidth:
    bw=bandwidth.replace('kbps', '* 1e3')
elif "Mbps" in bandwidth:
    bw=bandwidth.replace('Mbps', '* 1e6')
elif "Gbps" in bandwidth:
    bw=bandwidth.replace('Gbps', '* 1e9')
else:
    bw='0'
bw_int = eval(bandwidth)

当然,请确保您的输入是安全的,并且evalWhy is using 'eval' a bad practice?)有一些安全性和性能方面的考虑,但是有时,您只是想快速了解一下:)