python - 有没有办法自动生成有效的算术表达式?

标签 python parsing

我目前正在尝试创建一个 Python 脚本,该脚本将自动生成有效的以空格分隔的算术表达式。但是,我得到的示例输出如下所示:( 32 - 42/95 + 24 ( ) ( 53 ) + ) 21

虽然空括号对我来说完全没问题,但我不能在计算中使用这个自动生成的表达式,因为 24 和 53 之间没有运算符,最后 21 之前的 + 没有第二个参数。

我想知道的是,有没有办法使用 Pythonic 解决方案来解释/修复这些错误? (在任何人指出之前,我将第一个承认我在下面发布的代码可能是我推出并符合的最糟糕的代码……好吧,Python 的核心原则很少。)

import random
parentheses = ['(',')']
ops = ['+','-','*','/'] + parentheses

lines = 0

while lines < 1000:
    fname = open('test.txt','a')
    expr = []
    numExpr = lines
    if (numExpr % 2 == 0):
        numExpr += 1
    isDiv = False # Boolean var, makes sure there's no Div by 0

    # isNumber, isParentheses, isOp determine whether next element is a number, parentheses, or operator, respectively
    isNumber = random.randint(0,1) == 0 # determines whether to start sequence with number or parentheses
    isParentheses = not isNumber
    isOp = False
    # Counts parentheses to ensure parentheses are matching
    numParentheses = 0
    while (numExpr > 0 or numParentheses > 0):
        if (numExpr < 0 and numParentheses > 0):
            isDiv = False
            expr.append(')')
            numParentheses -= 1
        elif (isOp and numParentheses > 0):
            rand = random.randint(0,5)
            expr.append(ops[rand])
            isDiv = (rand == 3) # True if div op was just appended
            # Checks to see if ')' was appended
            if (rand == 5):
                isNumber = False
                isOp = True
                numParentheses -= 1
            # Checks to see if '(' was appended
            elif (rand == 4):
                isNumber = True
                isOp = False
                numParentheses += 1
            # All other operations go here
            else:
                isNumber = True
                isOp = False
        # Didn't add parentheses possibility here in case expression in parentheses somehow reaches 0
        elif (isNumber and isDiv):
            expr.append(str(random.randint(1,100)))
            isDiv = False
            isNumber = False
            isOp = True
        # If a number's up, decides whether to append parentheses or a number
        elif (isNumber):
            rand = random.randint(0,1)
            if (rand == 0):
                expr.append(str(random.randint(0,100)))
                isNumber = False
                isOp = True
            elif (rand == 1):
                if (numParentheses == 0):
                    expr.append('(')
                    numParentheses += 1
                else:
                    rand = random.randint(0,1)
                    expr.append(parentheses[rand])
                    if rand == 0:
                        numParentheses += 1
                    else:
                        numParentheses -= 1
            isDiv = False
        numExpr -= 1

    fname.write(' '.join(expr) + '\n')
    fname.close()
    lines += 1

最佳答案

是的,您可以用 Pythonic 的方式生成随机算术表达式。不过,您需要改变方法。不要尝试生成字符串并计算括号。而是生成一个随机的表达式树,然后输出它。

表达式树是指类的实例,例如,Expression 的子类 NumberPlusExpression、MinusExpression、'TimesExpressionDivideExpressionParenthesizedExpression。除了 Number 之外,每一个都将具有 Expression 类型的字段。给每个合适的 __str__ 方法。生成一些随机表达式对象并只打印“根”。

你可以从这里拿走它还是你想让我把它编码起来?

附录:一些示例入门代码。不生成随机表达式(还没有?)但是可以添加....

# This is just the very beginning of a script that can be used to process
# arithmetic expressions.  At the moment it just defines a few classes
# and prints a couple example expressions.

# Possible additions include methods to evaluate expressions and generate
# some random expressions.

class Expression:
    pass

class Number(Expression):
    def __init__(self, num):
        self.num = num

    def __str__(self):
        return str(self.num)

class BinaryExpression(Expression):
    def __init__(self, left, op, right):
        self.left = left
        self.op = op
        self.right = right

    def __str__(self):
        return str(self.left) + " " + self.op + " "  + str(self.right)

class ParenthesizedExpression(Expression):
    def __init__(self, exp):
        self.exp = exp

    def __str__(self):
        return "(" + str(self.exp) + ")"

e1 = Number(5)
print e1

e2 = BinaryExpression(Number(8), "+", ParenthesizedExpression(BinaryExpression(Number(7), "*", e1)))
print e2

** 附录 2 **

回到 Python 真的很有趣。我无法抗拒实现随机表达式生成器。它建立在上面的代码之上。抱歉硬编码!!

from random import random, randint, choice

def randomExpression(prob):
    p = random()
    if p > prob:
        return Number(randint(1, 100))
    elif randint(0, 1) == 0:
        return ParenthesizedExpression(randomExpression(prob / 1.2))
    else:
        left = randomExpression(prob / 1.2)
        op = choice(["+", "-", "*", "/"])
        right = randomExpression(prob / 1.2)
        return BinaryExpression(left, op, right)

for i in range(10):
    print(randomExpression(1))

这是我得到的输出:

(23)
86 + 84 + 87 / (96 - 46) / 59
((((49)))) + ((46))
76 + 18 + 4 - (98) - 7 / 15
(((73)))
(55) - (54) * 55 + 92 - 13 - ((36))
(78) - (7 / 56 * 33)
(81) - 18 * (((8)) * 59 - 14)
(((89)))
(59)

不太漂亮。我认为这让太多的 parent 失望了。也许改变在括号表达式和二进制表达式之间进行选择的概率可能会很好......

关于python - 有没有办法自动生成有效的算术表达式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6881170/

相关文章:

python - 为什么有些 Python 标准库是用 .so 编写的,而大多数其他库是用 .py 编写的?

android - 如何检查在android中的Jsoup html解析器中是否存在标签

python - 在Docker容器中为python使用配置文件

python - 具有自动补全功能的 QComboBox 在 PyQt4 中有效,但在 PySide 中无效

c# - 从 C# 运行 Python 函数

parsing - 大规模抓取/解析的技术是什么?

php - 使用 PHP Simple HTML DOM Parser 查找带有类的 div

python - 将 pandas 中的单元格值替换为元组

java - 如何将String解析为对象

c# - 无法使用 Json.Net 反序列化指数数值