2011-09-27 96 views
4

我正在將部分C++程序轉換爲Python,但我在替換C++函數strtod時遇到了一些麻煩。 我正在處理的字符串包含簡單的數學方程式,如「KM/1000.0」。問題是這兩個常量和數字是混合的,因此我無法使用float()。相當於C++的Python strtod

如何寫一個Python函數來模擬C++ strtod,它返回轉換後的數字和下一個字符的位置?

+0

你就不能分裂字符串提前? – Hubro

+0

你是否需要解析指數符號? –

+0

http://stackoverflow.com/questions/385558/python-and-regex-question-extract-float-double-value/385597#385597 – jfs

回答

3

我不知道任何現有的功能,將做到這一點。

然而,這是很容易寫一個使用正則表達式:

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) 

更好的整體辦法可能是建立一個lexical scanner,將第一令牌化的表達,然後與標記序列工作,而不是直接與字符串(或者實際上去整個豬,並建立一個YACC風格的解析器)。

+0

正則表達式再次敲擊! 謝謝,完美的作品。 – Waws

0

我會使用一個正則表達式是:

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) 
+0

'.1'呢? – jfs

+0

我能想到一堆無法拾起的有效浮點數。 – NPE

+0

正則表達式假定一個整數部分。其他一切都是可選的。如果有小數點,則需要小數部分。所以'.1'和'1.'不會被拾取。當然,如果需要的話修改正則表達式是很微不足道的。 –

0

自己解析數字。

遞歸下降解析器對於這種輸入非常容易。 先寫一本語法:

float ::= ipart ('.' fpart)* ('e' exp)* 
ipart ::= digit+ 
fpart ::= digit+ 
exp ::= ('+'|'-') digit+ 
digit = ['0'|'1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9'] 

現在這個語法轉化爲函數應該是簡單的......