C++ プログラムの一部を Python に変換する作業を行っていますが、C 関数strtodを置き換えるのに問題があります。私が取り組んでいる文字列は、「KM/1000.0」などの単純な数学っぽい方程式で構成されています。問題は、定数と数値の両方が混在しているため、float() を使用できないことです。
strtod
変換された数値と次の文字の位置の両方を返すPython 関数をシミュレートするにはどうすればよいでしょうか?
私はそれを行う既存の機能を知りません。
ただし、正規表現を使用して記述するのは非常に簡単です。
import re
# returns (float,endpos)
def strtod(s, pos):
m = re.match(r'[+-]?\d*[.]?\d*(?:[eE][+-]?\d+)?', s[pos:])
if m.group(0) == '': raise ValueError('bad float: %s' % s[pos:])
return float(m.group(0)), pos + m.end()
print strtod('(a+2.0)/1e-1', 3)
print strtod('(a+2.0)/1e-1', 8)
より良い全体的なアプローチは、最初に式をトークン化してから、文字列を直接処理するのではなく、一連のトークンを処理する字句スキャナーを構築することです (または、完全に独り占めして yacc スタイルのパーサーを構築します)。
自分で番号を解析します。
この種の入力では、再帰下降パーサーは非常に簡単です。最初に文法を書きます:
float ::= ipart ('.' fpart)* ('e' exp)*
ipart ::= digit+
fpart ::= digit+
exp ::= ('+'|'-') digit+
digit = ['0'|'1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9']
これで、この文法を関数に変換するのは簡単なはずです...
これには正規表現を使用します。
import re
mystring = "1.3 times 456.789 equals 593.8257 (or 5.93E2)"
def findfloats(s):
regex = re.compile(r"[+-]?\b\d+(?:\.\d+)?(?:e[+-]?\d+)?\b", re.I)
for match in regex.finditer(mystring):
yield (match.group(), match.start(), match.end())
これにより、文字列内のすべての浮動小数点数が検索され、それらの位置と共に返されます。
>>> for item in findfloats(mystring):
... print(item)
...
('1.3', 0, 3)
('456.789', 10, 17)
('593.8257', 25, 33)
('5.93E2', 38, 44)