如何在Python中评估自定义数学表达式

tay*_*ron 6 python math eval

我在python中编写了一个自定义骰子滚动解析器(如果必须,可以使用snicker).基本上,我想使用标准数学评估,但添加'd'运算符:

#xdy
sum = 0
for each in range(x):
    sum += randInt(1, y)
return sum
Run Code Online (Sandbox Code Playgroud)

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

我正在使用正则表达式来替换所有'和s,然后使用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())
Run Code Online (Sandbox Code Playgroud)

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

unu*_*tbu 6

你可以使用一个回调函数re.sub.当您点击链接时,请向下搜索以"如果repl是一个函数..."开头的段落

import re
import random

def xdy(matchobj):
    x,y=map(int,matchobj.groups())
    s = 0
    for each in range(x):
        s += random.randint(1, y)
    return str(s)
s='1d6+2d6+2d6-72+4d100'
t=re.sub('(\d+)d(\d+)',xdy,s)
print(t)
# 5+10+8-72+197
print(eval(t))
# 148
Run Code Online (Sandbox Code Playgroud)


Mar*_*tos 5

Python不会让你编写全新的操作符,也不能用常规语言做括号.你必须编写一个递归下降解析器.对于你的骰子滚动语言,这应该是非常简单的.

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