在python中,如何使用人类可读的单位计算数学表达式?

在python中,如何使用人类可读的单位计算数学表达式?,python,expression,evaluation,units-of-measurement,Python,Expression,Evaluation,Units Of Measurement,有没有一种方法可以从包含人类可读数字单位的字符串中计算表达式 例如: myformula='1u+1e-6' result = eval(myformula) 。。。应等同于1e-6+1e-6,其中u=微 myformula='1u+1e-6' result = eval(re.sub("(\d+)u","\\1e-6",myformula)) 应该有用。。。在评估之前,只需用e-6替换紧跟在u后面的任何数字这个答案在Joran的基础上有所扩展,用适当的指数替换所有数字: import re

有没有一种方法可以从包含人类可读数字单位的字符串中计算表达式

例如:

myformula='1u+1e-6'
result = eval(myformula)
。。。应等同于1e-6+1e-6,其中u=微

myformula='1u+1e-6'
result = eval(re.sub("(\d+)u","\\1e-6",myformula))

应该有用。。。在评估之前,只需用e-6替换紧跟在u后面的任何数字

这个答案在Joran的基础上有所扩展,用适当的指数替换所有数字:

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)
接下来,我们定义一个repl_si,它在si中查找匹配项,并将其替换为与指数连接的e

然后,我们所要做的就是编写一个函数,用正则表达式、替换函数和公式适当地调用re.sub,瞧:


现在,您需要做的就是调用结果的eval,当然您应该使用用户提供的输入。添加一个答案,主要是受Joran的启发,它可能没有Zero的那么优雅,但我认为它可以做到这一点 有一件事我确保该单元前面必须有一个数字\d+

我通过在不同单位上处理一系列替代品来固定单位

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将作为
1e18+3e15+0.5e12-7e9-6e6+2.5e3-1e-3+3.7e-6+4e-9+13e-12-59e-15-73e-18+0.5e-5

1u如何比1e-6更具可读性。。。你也提到了哪些人?这可能是一个很好的学习练习,可以让你自己创建这种解析器。在现实生活中肯定不需要@乔兰比斯利:从符号的选择来看,听起来应该是科学家和工程师——他们和我们一样都是人;作为一名科学家,我永远不会只给出一个“微”或“纳米”或任何东西,除非单位是附加的——“微升”、“千克”等。我从来没有见过任何人只使用前缀…为什么是1u而不是1µ?:为什么是-1?我觉得这回答了我的问题。。。如果没有,请解释为什么没有谢谢,我如何才能强制转换只有当单位跟踪一个数字直接[0-9],我觉得差异可以在SI_REGEX表达式这里有一个安全的方法来处理用户输入的数学表达式在python中@山姆·弗里曼:是的,这是可能的,在正则表达式中使用lookback断言。类似的东西应该可以用:SI_REGEX=re.compiler?@sam.freeman我已经采纳了Håken的建议,因此只有当词缀前面有一个数字时才能进行替换。谢谢@HåkenLid:-你的解决方案和我的解决方案之间的主要区别是,它必须多次处理公式,而不是一次。除非性能是一个问题,否则这不是一个问题,但是是的,编写几乎相同的代码行十几次确实有点不雅观。没有什么可以阻止你在dict上迭代,但是。。。
>>> 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'
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)