I have looked in the standard library and on StackOverflow, and have not found a similar question. So, is there a way to do the following without rolling my own function? Bo
I wrote the following method that should always return the output to the exact same accuracy as the input, with no floating point errors such as in the other answers.
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:])
i
(the index the decimal place was at) by 2, because we want to shift the decimal place 2 spaces to the left.i
is negative, then we need to pad with zeros.
Test case (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)
Use strip('%')
, as:
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
Based on the answer from @WKPlus this solution takes into account the locales where the decimal point is either a point .
or a comma ,
float("-3,5%".replace(',','.')[:-1]) / 100
float(stringPercent.strip('%')) / 100.0
Another way:
float(stringPercent[:-1]) / 100