如何在Python中评估自定义数学表达式 [英] How to evaluate a custom math expression in Python

查看:131
本文介绍了如何在Python中评估自定义数学表达式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在用python编写一个自定义骰子滚动解析器(如果需要的话,更昵称).基本上,我想使用标准的数学评估,但要添加'd'运算符:

#xdy
sum = 0
for each in range(x):
    sum += randInt(1, y)
return sum

例如1d6 + 2d6 + 2d6-72 + 4d100 =(5)+(1 + 1)+(6 + 2)-72+(5 + 39 + 38 + 59)= 84

我当时使用正则表达式用总和替换所有'd',然后使用eval,但是当处理任何一侧的括号时,我的正则表达式都崩溃了.有比实现我自己的递归解析更快的方法吗?也许在eval中添加一个运算符?

我似乎给出了一个错误的示例,因为上面的示例适用于当前版本.我正在寻找某种评估方式,例如(5+(6d6))d(7-2 *(1d4)).
分崩离析",我的意思是我当前的正则表达式表达失败. 对于失败我一直含糊其词,对于造成的混乱,我深表歉意.这是我当前的代码:

def evalDice(roll_matchgroup):
    roll_split = roll_matchgroup.group('roll').split('d')
    print roll_split
    roll_list = []

    for die in range(int(roll_split[0])):
        roll = random.randint(1,int(roll_split[1]))
        roll_list.append(roll)

def EvalRoll(roll):
    if not roll: return 0
    rollPattern = re.compile('(?P<roll>\d*d\d+)')
    roll_string = rollPattern.sub(evalDice, roll.lower())

为此,"1d6 + 4d100"工作正常,但(1d6 + 4)d100"甚至"1d6 + 4d(100)"失败.

解决方案

Python不允许您编写全新的运算符,也不能使用常规语言进行括号.您必须编写一个递归下降解析器.不过,对于您的掷骰子语言来说,这应该非常简单.

或者,您可以采用现有的Python运算符,并使用Python的解析工具将文本转换为AST.

I'm writing a custom dice rolling parser (snicker if you must) in python. Basically, I want to use standard math evaluation but add the 'd' operator:

#xdy
sum = 0
for each in range(x):
    sum += randInt(1, y)
return sum

So that, for example, 1d6+2d6+2d6-72+4d100 = (5)+(1+1)+(6+2)-72+(5+39+38+59) = 84

I was using regex to replace all 'd's with the sum and then using eval, but my regex fell apart when dealing with parentheses on either side. Is there a faster way to go about this than implementing my own recursive parsing? Perhaps adding an operator to eval?

Edit: I seem to have given a bad example, as the above example works with my current version. What I'm looking for is some way to evaluate, say, (5+(6d6))d(7-2*(1d4)).
By "fell apart", I just meant that my current regex expression failed. I have been too vague about my failure, sorry for the confusion. Here's my current code:

def evalDice(roll_matchgroup):
    roll_split = roll_matchgroup.group('roll').split('d')
    print roll_split
    roll_list = []

    for die in range(int(roll_split[0])):
        roll = random.randint(1,int(roll_split[1]))
        roll_list.append(roll)

def EvalRoll(roll):
    if not roll: return 0
    rollPattern = re.compile('(?P<roll>\d*d\d+)')
    roll_string = rollPattern.sub(evalDice, roll.lower())

for this, "1d6+4d100" works just fine, but "(1d6+4)d100" or even "1d6+4d(100)" fails.

解决方案

Python doesn't let you write brand new operators, and you can't do parentheses with a regular language. You'll have to write a recursive descent parser. This should be pretty simple for your dice-rolling language though.

Alternatively, you could coopt an existing Python operator and use Pythons parsing tools to convert the text into an AST.

这篇关于如何在Python中评估自定义数学表达式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆