web-dev-qa-db-ja.com

文字列パーセントを浮動小数点数に変換するクリーンな方法は何ですか?

標準ライブラリとStackOverflowを調べましたが、同様の質問は見つかりませんでした。それで、自分の機能を実行せずに以下を実行する方法はありますか?組み込みの方法がない場合に誰かが美しい関数を書くと、ボーナスポイントが発生します。

def stringPercentToFloat(stringPercent)
    # ???
    return floatPercent

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

>>>> 0.99
>>>> 0.995
26
Wulfram

次のように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
50
float(stringPercent.strip('%')) / 100.0
16
Mark Ransom

別の方法:float(stringPercent[:-1]) / 100

2
WKPlus

他の回答のような浮動小数点エラーがなく、常に入力とまったく同じ精度で出力を返す必要がある次のメソッドを作成しました。

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. フロートに変換します。

テストケース( オンラインで試す ):

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)
2
Hat