我编写了以下方法,该方法应始终将输出返回到与输入完全相同的精度,并且没有其他答案中的浮点错误。
def percent_to_float(s):
s = str(float(s.rstrip("%")))
i = s.find(".")
if i == -1:
return int(s) / 100
if s.startswith("-"):
return -percent_to_float(s.lstrip("-"))
s = s.replace(".", "")
i -= 2
if i < 0:
return float("." + "0" * abs(i) + s)
else:
return float(s[:i] + "." + s[i:])
解释
- 从末尾去掉“%”。
- 如果 percent 没有“.”,只需将其除以 100 即可返回。
- 如果百分比是负数,去掉“-”并重新调用函数,然后将结果转换回负数并返回。
- 去掉小数位。
- 将(小数点所在的索引)减
i
2,因为我们要将小数点左移 2 个空格。
- 如果
i
是负数,那么我们需要用零填充。
- 示例:假设输入为“1.33%”。为了能够将小数位向左移动 2 个空格,我们需要用零填充。
- 转换为浮点数。
测试用例(在线试用):
from unittest.case import TestCase
class ParsePercentCase(TestCase):
tests = {
"150%" : 1.5,
"100%" : 1,
"99%" : 0.99,
"99.999%" : 0.99999,
"99.5%" : 0.995,
"95%" : 0.95,
"90%" : 0.9,
"50%" : 0.5,
"66.666%" : 0.66666,
"42%" : 0.42,
"20.5%" : 0.205,
"20%" : 0.2,
"10%" : 0.1,
"3.141592653589793%": 0.03141592653589793,
"1%" : 0.01,
"0.1%" : 0.001,
"0.01%" : 0.0001,
"0%" : 0,
}
tests = sorted(tests.items(), key=lambda x: -x[1])
def test_parse_percent(self):
for percent_str, expected in self.tests:
parsed = percent_to_float(percent_str)
self.assertEqual(expected, parsed, percent_str)
def test_parse_percent_negative(self):
negative_tests = [("-" + s, -f) for s, f in self.tests]
for percent_str, expected in negative_tests:
parsed = percent_to_float(percent_str)
self.assertEqual(expected, parsed, percent_str)