开发者

Python equivalent to atoi / atof

Python loves raising exceptions, which is usually great. But I'm facing some strings I desperately want to convert to integers using C's atoi / atof semantics - e.g. atoi of "3 of 12", "3/12", "3 / 12", should all become 3; atof("3.14 seconds") should become 3.14; atoi(" -99 score") should become -99. Python of course has atoi and atof functions, which behave nothing like atoi and atof and exactly like Python's own int and float constructors.

The best I have so far, which is really ugly and hard to extend to the various float formats available:

value = 1
s = str(s).strip()
if s.startswith("-"):
    value = -1
    s = s[1:]
elif s.startswith("+"):
    s = s[1:]
try:开发者_如何学JAVA
    mul = int("".join(itertools.takewhile(str.isdigit, s)))
except (TypeError, ValueError, AttributeError):
    mul = 0
return mul * value


If you're so keen on getting exactly the functionality of c's atoi, why not use it directly? E.g., on my Mac,

>>> import ctypes, ctypes.util
>>> whereislib = ctypes.util.find_library('c')
>>> whereislib
'/usr/lib/libc.dylib'
>>> clib = ctypes.cdll.LoadLibrary(whereislib)
>>> clib.atoi('-99foobar')
-99

In Linux, Windows, etc, identical code should work except that you'll see a different path if you examine whereislib (only on really, really peculiar installations should this code ever fail to find the C runtime library).

If you're keen on avoiding direct C library usage, I guess you could grab the relevant prefix, e.g. with a RE such as r'\s*([+-]?\d+)', and try int on that.


I think the iterative version is better than the recursive version

# Iterative
def atof(s):
    s,_,_=s.partition(' ') # eg. this helps by trimming off at the first space
    while s:
        try:
            return float(s)
        except:
            s=s[:-1]
    return 0.0

# Recursive
def atof(s):
    try:
        return float(s)
    except:
        if not s:
            return 0.0
        return atof(s[:-1])


print atof("3 of 12")
print atof("3/12")
print atof("3 / 12")
print atof("3.14 seconds")
print atof("314e-2 seconds")
print atof("-99 score")
print atof("hello world")


Perhaps use a quick regex to grab only the first part of the string that can be considered numeric? Something like...

-?[0-9]+(?:\.[0-9]+)?

for floats and for ints just,

-?[0-9]+


It's pretty straightforward to do this with regular expressions:

>>> import re
>>> p = re.compile(r'[^\d-]*(-?[\d]+(\.[\d]*)?([eE][+-]?[\d]+)?)')
>>> def test(seq):
        for s in seq:
            m = p.match(s)
            if m:
                result = m.groups()[0]
                if "." in result or "e" in result or "E" in result:
                    print "{0} -> {1}".format(s, float(result))
                else:
                    print '"{0}" -> {1}'.format(s, int(result))
            else:
                print s, "no match"

>>> test(s)
"1 0" -> 1
"3 of 12" -> 3
"3 1/2" -> 3
"3/12" -> 3
3.15 seconds -> 3.15
3.0E+102 -> 3e+102
"what about 2?" -> 2
"what about -2?" -> -2
2.10a -> 2.1


I think I will do it char by char:

def myatof(s):
    try:
        return float(s);
    except:
        last_result = None
        for i in range(1, len(s)):
            try:
                last_result = float(s[:i])
            except:
                return last_result
    return last_result


How about this?

num=int(q.join(re.findall(r'[\d-]',s)))


This Solution is very simple, Basically The difference B/W the ASCII Value of the digit and the ASCII value of zero is the digit based on the length of the input string, here I traverse the string in reverse based on the position of each digit from Units place to the n'th place and multiply each digit by the equivalent 10^n, will work only for n O(n) Time space| GG | #BasicMath

def aToI(st1):
    
    n  = len(st1)
    
    count = 1
    res = 0
    for i in range(n -1,-1,-1):
        #print(st1[i])
        x = ord(st1[i]) - ord('0')
        res += (x*count)
        
        count = count * 10
    print(res)
s = input()
aToI(s)
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜