#1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2005
    Posts
    2
    Rep Power
    0

    how can I get a string evaluated as I expected?


    Hello,

    I get a line from a file like this:

    cgbo = 1.0e-9

    I want to know whether cgbo is equal to 0, so I do:

    cgbo = re.sub(r'^.*=', '',line)
    if eval(cgbo)==0:
    # do something here ...

    But sometimes, the line looks like this:

    cgbo = 1.0e-9*(160/(300+500))

    eval(cgbo) will give 0 because (160/500) is 0 in python. But
    I expect it is done in float and give me back 2.0e-10

    How can I achieve this?

    Thanks a lot for your ideas.

    xbguan
  2. #2
  3. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Dec 2004
    Location
    Regensburg, Germany
    Posts
    147
    Rep Power
    17
    Try this:

    Code:
    cgbo = re.sub("(?<=[(])(?P<int>\d+)(?=[)+*/-])", "\g<int>.0",
                  re.sub(r'^.*=', '',line))
    It appends ".0" to all integers following an opening parenthesis of an expression, so everything within the parenthesis evaluates to float.
    It requires that the expression does not contain whitespace. It's not fully tested, but it works for the example you provided.

    Be careful with using the eval function. There are several threads in this forum dealing with this topic (search this forum for "eval(").
  4. #3
  5. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Feb 2005
    Posts
    78
    Rep Power
    10
    Originally Posted by xbguan
    But sometimes, the line looks like this:

    cgbo = 1.0e-9*(160/(300+500))

    eval(cgbo) will give 0 because (160/500) is 0 in python. But
    I expect it is done in float and give me back 2.0e-10
    Code:
    from __future__ import division
    print 1/2
    print 1//2
    line = "cgbo = 1.0e-9*(160/(300+500))"
    varnam, expression = line.split("=")
    print eval(expression)
    If you need to use division, you should always use from __future__ import division as it forces "/" to return a float if necessary ("//" does integer division)

    BTW, in Python, if you're using a regex and your expression to match is simple then there's probably a Pythonic non-regex way to do it...

    --OH.
  6. #4
  7. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Feb 2005
    Posts
    78
    Rep Power
    10
    Originally Posted by sbkwi
    Be careful with using the eval function. There are several threads in this forum dealing with this topic (search this forum for "eval(").
    True. If the values were only numbers, he should just be using float(). The problem is that they can be full expressions. Really, he'd need to implement (or find and download) a parser for mathematical expressions to be safe...

    or (dare I say it) use a regex to verify...

    he could probably just use the following though:
    Code:
    def check_expression(expression):
        for char in expression:
            if char not in ("0123456789()/*+-.e"):
                return False
        return True
    I don't _think_ that's exploitable (since the only letter it allows is "e") ...

    --OH.
  8. #5
  9. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2005
    Posts
    2
    Rep Power
    0
    Thank you hydroxide and sbkwi for your ideas.

    I came up with an idea later yesterday which is very close to sbkwi's. I
    didn't replace the integers with its float version. I replaced '/' with '*1.0/'.

    But I likes 'from __future__ import division' better. I will go with it if I learned it earlier.

IMN logo majestic logo threadwatch logo seochat tools logo