Is there a way to evaluate expressions from strings that include human readable number units?
For example:
myformula='1u+1e-6'
result = eval(myformula)
... should be equivalent to 1e-6+1e-6
(where u=micro).
Is there a way to evaluate expressions from strings that include human readable number units?
For example:
myformula='1u+1e-6'
result = eval(myformula)
... should be equivalent to 1e-6+1e-6
(where u=micro).
This answer expands somewhat on Joran's to replace all SI affices with the appropriate exponents:
import re
SI = {
"T": 12,
"G": 9,
"M": 6,
"k": 3,
"h": 2,
"da": 1,
"d": -1,
"c": -2,
"m": -3,
"u": -6,
"n": -9,
"p": -12,
}
SI_REGEX = re.compile(r"(?<=\d)(%s)\b" % "|".join(SI))
def repl_si(match):
return "e%d" % SI[match.group()]
def defix(formula):
return re.sub(SI_REGEX, repl_si, formula)
Using the dictionary SI
, we create a regular expression that will match any of the keys in SI
as long as they're preceded by a digit and followed by a word boundary:
(?<=\d)(T|G|M|k|h|da|d|c|m|u|n|p)\b
Next, we define a substitution function repl_si()
that looks up the match in SI
and replaces it with "e"
concatenated with the exponent.
Then, all we have to do is write a function that calls re.sub()
appropriately with the regex, substitution function and formula, and voilà:
>>> defix("1T + 2G + 3M + 4k + 5h + 6da + 7d + 8c + 9m + 1u + 2n + 3p")
'1e12 + 2e9 + 3e6 + 4e3 + 5e2 + 6e1 + 7e-1 + 8e-2 + 9e-3 + 1e-6 + 2e-9 + 3e-12'
Now all you need to do is call eval()
on the result, which of course you should absolutely never do with user-supplied input.
myformula='1u+1e-6'
result = eval(re.sub("(\d+)u","\\1e-6",myformula))
should work... by just replacing any digits followed immediatly by u with e-6 before evaluating
Adding an answer, mostly inspired by Joran, it probably isn't as elegant as Zero's but I think it does the job one thing I made sure that the unit MUST be preceded by a numeric figure (\d+)
I fixed the units by processing a series of substitutes over different units
myformula = '1E+3P+0.5T-7G-6M+2.5k-1m+3.7u+4n+13p-59f-73a+0.5e-5'
tmp_exp = re.sub('(\d+)E', r'\1e18', myformula)
tmp_exp = re.sub('(\d+)P', r'\1e15', tmp_exp)
tmp_exp = re.sub('(\d+)T', r'\1e12', tmp_exp)
tmp_exp = re.sub('(\d+)G', r'\1e9', tmp_exp)
tmp_exp = re.sub('(\d+)M', r'\1e6', tmp_exp)
tmp_exp = re.sub('(\d+)k', r'\1e3', tmp_exp)
tmp_exp = re.sub('(\d+)m', r'\1e-3', tmp_exp)
tmp_exp = re.sub('(\d+)u', r'\1e-6', tmp_exp)
tmp_exp = re.sub('(\d+)n', r'\1e-9', tmp_exp)
tmp_exp = re.sub('(\d+)p', r'\1e-12', tmp_exp)
tmp_exp = re.sub('(\d+)f', r'\1e-15', tmp_exp)
tmp_exp = re.sub('(\d+)a', r'\1e-18', tmp_exp)
tmp_exp will come out as 1e18+3e15+0.5e12-7e9-6e6+2.5e3-1e-3+3.7e-6+4e-9+13e-12-59e-15-73e-18+0.5e-5