【问题标题】:What is a clean way to convert a string percent to a float?将字符串百分比转换为浮点数的干净方法是什么?
【发布时间】:2022-11-13 07:58:26
【问题描述】:

我查看了标准库和 StackOverflow,并没有找到类似的问题。那么,有没有办法在不滚动我自己的功能的情况下执行以下操作?如果有人在没有内置方法的情况下编写了一个漂亮的函数,则可以加分。

def stringPercentToFloat(stringPercent)
    # ???
    return floatPercent

p1 = "99%"
p2 = "99.5%"
print stringPercentToFloat(p1)
print stringPercentToFloat(p2)

>>>> 0.99
>>>> 0.995

【问题讨论】:

  • 问题从何而来?
  • 我有一个包含 CPU 使用百分比和内存使用百分比的日志,因此拥有此功能会很有帮助,这样我就可以对日志条目进行排序。
  • “......没有滚动我自己的功能?如果有人写了一个漂亮的功能,奖励积分。”这些是相互矛盾的要求吗?
  • 是的,这是一个相互矛盾的要求。我已经对其进行了更改以使其更加清晰。谢谢。

标签: python string python-2.7 python-3.x


【解决方案1】:

使用 strip('%') ,作为:

In [9]: "99.5%".strip('%')
Out[9]: '99.5'             #convert this to float using float() and divide by 100

In [10]: def p2f(x):
   ....:    return float(x.strip('%'))/100
   ....: 

In [12]: p2f("99%")
Out[12]: 0.98999999999999999

In [13]: p2f("99.5%")
Out[13]: 0.995

【讨论】:

  • 接受的答案不考虑语言环境。大多数时候小数点是句点(.),但在其他国家可能是逗号(,),所以转换会失败。
  • @krema 好吧,这超出了这个问题的范围。每次使用 float 进行转换时,提及 locale.atof 是没有意义的。
【解决方案2】:
float(stringPercent.strip('%')) / 100.0

【讨论】:

    【解决方案3】:

    在解析为 float 之前,只需将 % 替换为 e-2 即可:

    float("99.5%".replace('%', 'e-2'))
    

    它更安全,因为如果没有使用%,结果仍然是正确的。

    【讨论】:

    • 非常优雅的解决方案,不错
    【解决方案4】:

    我编写了以下方法,该方法应始终将输出返回到与输入完全相同的精度,并且没有其他答案中的浮点错误。

    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:])
    

    解释

    1. 从末尾去掉“%”。
    2. 如果百分比没有“.”,只需将其除以 100 即可返回。
    3. 如果百分比是负数,去掉“-”并重新调用函数,然后将结果转换回负数并返回。
    4. 删除小数位。
    5. 将i(小数位所在的索引)减 2,因为我们要将小数位向左移动 2 个空格。
    6. 如果i 是负数,那么我们需要用零填充。
      • 例子:假设输入是“1.33%”。为了能够将小数位向左移动 2 个空格,我们需要用零填充。
    7. 转换为浮点数。

      测试用例(Try it online):

      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)
      

    【讨论】:

    • 您白白做了很多工作,其他答案中没有浮点错误,而您的答案也没有。见stackoverflow.com/questions/588004/…
    • 好吧,例如在Ashwini's answer 中,您可以看到他的称为p2f("99%") 的单行方法返回0.98999999999999999,而如果您尝试在我的回答中运行测试用例,您会看到相同的输入字符串“99%”将为您提供0.99 的预期输出。您能否举一个我的方法的输入字符串示例,它会导致浮点错误?
    • 阅读我给你的链接。这是如何打印的问题,而不是实际值。随着 Ashwini 的回答,我在 Python 2.7.1 和 3.6.3 上都得到了 0.99 输出。由于整数除法,您的在 2.7.1 上返回 0。
    • 例如,'%0.20f' % parse_percent('99%')返回'0.98999999999999999112'
    • 好吧,我为 Python 3 编写了我的方法,之所以写它是因为这个问题的其他答案都没有,虽然简洁,但满足了我对 consistently returning a float value without floating point errors 的要求。
    【解决方案5】:

    根据@WKPlus 的回答,该解决方案考虑了小数点为点. 或逗号, 的语言环境

    float("-3,5%".replace(',','.')[:-1]) / 100
    

    【讨论】:

      【解决方案6】:

      另一种方式: float(stringPercent[:-1]) / 100

      【讨论】:

        猜你喜欢
        • 2022-08-03
        • 1970-01-01
        • 1970-01-01
        • 2015-08-25
        • 1970-01-01
        • 1970-01-01
        • 2011-11-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多