小数または有理数を表すことができる文字列を浮動小数点数に変換するにはどうすればよいですか
>>> ["0.1234", "1/2"]
['0.1234', '1/2']
[0.1234、0.5]が欲しいです。
eval は私が考えていたものですが、運はありません:
>>> eval("1/2")
0
小数または有理数を表すことができる文字列を浮動小数点数に変換するにはどうすればよいですか
>>> ["0.1234", "1/2"]
['0.1234', '1/2']
[0.1234、0.5]が欲しいです。
eval は私が考えていたものですが、運はありません:
>>> eval("1/2")
0
I'd parse the string if conversion fails:
>>> def convert(s):
try:
return float(s)
except ValueError:
num, denom = s.split('/')
return float(num) / float(denom)
...
>>> convert("0.1234")
0.1234
>>> convert("1/2")
0.5
Generally using eval is a bad idea, since it's a security risk. Especially if the string being evaluated came from outside the system.
As others have pointed out, using eval
is potentially a security risk, and certainly a bad habit to get into.
(if you don't think it's as risky as exec
, imagine eval
ing something like: __import__('os').system('rm -rf /')
)
However, if you have python 2.6 or up, you can use ast.literal_eval
, for which the string provided:
may only consist of the following Python literal structures: strings, numbers, tuples, lists, dicts, booleans, and None.
Thus it should be quite safe :-)
別のオプション (これも 2.6 以降のみ) はfractions
モジュールです。
>>> from fractions import Fraction
>>> Fraction("0.1234")
Fraction(617, 5000)
>>> Fraction("1/2")
Fraction(1, 2)
>>> float(Fraction("0.1234"))
0.1234
>>> float(Fraction("1/2"))
0.5
Use from __future__ import division
to get the behavior you want. Then, in a pinch, you can do something like
from __future__ import division
strings = ["0.1234", "1/2", "2/3"]
numbers = map(eval, strings)
to get a list of floats out of your strings. If you want to do this the "right" way, don't use eval()
, but instead write a function that accepts a string and calls float()
on it if it contains no slash, or parses the string and divides the numerator and denominator if there's a slash in it.
One way to do it:
def parse_float_string(x)
parts = x.split('/', 1)
if len(parts) == 1:
return float(x)
elif len(parts) == 2:
return float(parts[0])/float(parts[1])
else:
raise ValueError
Then just map(parse_float_string, strings)
will get you your list.
/
演算子は整数除算を行います。試す:
>>> eval("1.0*" + "1/2")
0.5
は潜在的に危険であるためeval()
、渡す内容を常に正確に確認する必要があります。
>>> import re
>>> s = "1/2"
>>> if re.match(r"\d+/\d+$", s):
... eval("1.0*" + s)
...
0.5
ただし、そもそも入力を正規表現と照合するのに苦労する場合はr"(\d+)/(\d+)$"
、分子と分母を抽出し、自分で除算を行い、完全に回避するために使用することもできeval()
ます。
>>> m = re.match(r"(\d+)/(\d+)$", s)
>>> if m:
... float(m.group(1)) / float(m.group(2))
...
0.5
The problem with eval is that, as in python, the quotient of integers is an integer. So, you have several choices.
The first is simply to make integer division return floats:
from __future__ import division
The other is to split the rational number:
reduce(lambda x, y: x*y, map(int, rat_str.split("/")), 1)
Where rat_str is the string with a rational number.
Python 3では、これは機能するはずです。
>>> x = ["0.1234", "1/2"]
>>> [eval(i) for i in x]
[0.1234, 0.5]
sympyはここであなたを助けることができます:
import sympy
half = sympy.Rational('1/2')
p1234 = sympy.Rational('0.1234')
print '%f, %f" % (half, p1234)
The suggestions with from __future__ import division
combined with eval
will certainly work.
It's probably worth pointing out that the suggestions that don't use eval
but rather parse the string do so because eval
is dangerous: if there is some way for an arbitrary string to get sent to eval
, then your system is vulnerable. So it's a bad habit. (But if this is just quick and dirty code, it's probably not that big a deal!)
これは、1 と 2 が Python によって浮動小数点数ではなく整数として解釈されるためです。1.0/2.0 またはその混合である必要があります。