我正在尝试创建一个将方程式作为输入并基于运算进行求值的函数,规则是我应该在运算符之间(*,+,-,%,^) 正确的数学表达式,例如:
Int
原因:*旁边有另一个*,而不是数字或数学表达式
Input: 6**8
Result: Not correct
原因:“-”在开头,并且不在两个数字之间。
Input: -6+2
Result: Not correct
原因:“ *”在数学上正确的表达式“(2 + 3)
旁边答案 0 :(得分:1)
eval
带有try-except的表达式:
try:
result = eval(expression)
correct_sign = True
except SyntaxError:
correct_sign = False
优势:
缺点:
在编译器中使用算法,使数学表达式对于pc可读。这些算法也可以用于评估表达式是否有效。 我不打算解释这些算法。外面有足够的资源。
这是您可以做的非常简短的结构:
您需要了解后缀和中缀表达式的含义。
资源:
调车场算法:https://en.wikipedia.org/wiki/Shunting-yard_algorithm
反向抛光符号/后修复符号:https://en.wikipedia.org/wiki/Reverse_Polish_notation
Python内置令牌生成器:https://docs.python.org/3.7/library/tokenize.html
优势:
缺点
答案 1 :(得分:1)
如评论中所述,这称为parsing
,并且需要语法。
查看带有PEG
解析器parsimonious
的示例:
from parsimonious.grammar import Grammar
from parsimonious.nodes import NodeVisitor
from parsimonious.exceptions import ParseError
grammar = Grammar(
r"""
expr = (term operator term)+
term = (lpar factor rpar) / number
factor = (number operator number)
operator = ws? (mod / mult / sub / add) ws?
add = "+"
sub = "-"
mult = "*"
mod = "/"
number = ~"\d+(?:\.\d+)?"
lpar = ws? "(" ws?
rpar = ws? ")" ws?
ws = ~"\s+"
"""
)
class SimpleCalculator(NodeVisitor):
def generic_visit(self, node, children):
return children or node
def visit_expr(self, node, children):
return self.calc(children[0])
def visit_operator(self, node, children):
_, operator, *_ = node
return operator
def visit_term(self, node, children):
child = children[0]
if isinstance(child, list):
_, factor, *_ = child
return factor
else:
return child
def visit_factor(self, node, children):
return self.calc(children)
def calc(self, params):
""" Calculates the actual equation. """
x, op, y = params
op = op.text
if not isinstance(x, float):
x = float(x.text)
if not isinstance(y, float):
y = float(y.text)
if op == "+":
return x+y
elif op == "-":
return x-y
elif op == "/":
return x/y
elif op == "*":
return x*y
equations = ["6 *(2+3)", "2+2", "4*8", "123-23", "-1+1", "100/10", "6**6"]
c = SimpleCalculator()
for equation in equations:
try:
tree = grammar.parse(equation)
result = c.visit(tree)
print("{} = {}".format(equation, result))
except ParseError:
print("The equation {} could not be parsed.".format(equation))
这产生
6 *(2+3) = 30.0
2+2 = 4.0
4*8 = 32.0
123-23 = 100.0
The equation -1+1 could not be parsed.
100/10 = 10.0
The equation 6**6 could not be parsed.
答案 2 :(得分:0)
您需要使用正确的数据结构和算法来实现解析数学方程式并对其进行评估的目标。 另外,您还必须熟悉两个概念:用于创建解析器的 堆栈 和 树 。
认为您可以使用的最佳算法是RPN(反向波兰表示法)。
答案 3 :(得分:0)
对于问题1,您始终可以在评估之前去除括号。
input_string = "6*(2+3)"
it = filter(lambda x: x != '(' and x != ')', input_string)
after = ' '.join(list(it))
print(after)
# prints "6 * 2 + 3"
答案 4 :(得分:0)
似乎您可能刚刚开始使用python。总有很多方法可以解决问题。一种让您快速入门的有趣方法是考虑根据运算符拆分方程式。
例如,以下代码使用正则表达式拆分公式:
import re
>>> formula2 = '6+3+5--5'
>>> re.split(r'\*|\/|\%|\^|\+|\-',formula2)
['6', '3', '5', '', '5']
>>> formula3 = '-2+5'
>>> re.split(r'\*|\/|\%|\^|\+|\-',formula3)
['', '2', '5']
它可能看起来很复杂,但是在r'\*|\/|\%|\^|\+|\-'
片断中,\表示从字面上接受下一个字符,而|则表示|。表示“或”,因此它会评估将其中一个运算符拆分。
在这种情况下,您会发现,任何时候同时存在两个运算符,或者公式以一个运算符开头时,您的列表中将有一个空白值-第二个为一个-第一个公式为一个领先-在第二个公式中。
基于此,您可以说:
if '' in re.split(r'\*|\/|\%|\^|\+|\-',formula):
correctsign = False
也许这可以作为让大脑思考解决问题的有趣方法的良好起点。
答案 5 :(得分:0)
首先要提到**
代表幂,即6**8
:6等于8的幂。
算法背后的逻辑是错误的,因为在代码中,响应仅取决于最后一位数字/符号是否满足您的条件。这是因为一旦循环完成,基于最后一位数字/符号,您的布尔值correctsigns
默认为True
或False
。
您也可以使用elif
代替嵌套的else
语句来获得更简洁的代码。
在不更改核心算法的情况下,您的代码将如下所示:
def checksigns(equation):
signs = ["*","/","%","^","+","-"]
for i in signs:
if i in equation:
index = equation.index((i))
if (equation[index] == equation[0]):
return "Not correct"
elif (equation[index] == equation[len(equation) - 1]):
return "Not correct"
elif (equation[index + 1].isdigit() and equation[index - 1].isdigit()):
return "Correct"
else:
return "Not correct"
答案 6 :(得分:0)
您可以使用Python的ast模块来解析表达式:
public class StockConfiguration : IEntityTypeConfiguration<Stock>
{
public void Configure(EntityTypeBuilder<Stock> builder)
{
builder
.ToTable("Stocks");
builder
.Property<int>("StockID")
.HasColumnType("int")
.ValueGeneratedOnAdd()
.HasAnnotation("Key", 0);
builder
.Property(stock => stock.Name)
.HasColumnName("Name")
.HasMaxLength(25)
.IsRequired();
builder
.HasMany(stock => stock.Transactions)
.WithOne(transaction => transaction.RelatedStock)
.IsRequired();
builder
.HasIndex(stock => stock.Name)
.IsUnique();
}
}
第一种情况import ast
import itertools as it
def check(expr):
allowed = (ast.Add, ast.Sub, ast.Mult, ast.Mod)
try:
for node in it.islice(ast.walk(ast.parse(expr)), 2, None):
if isinstance(node, (ast.BinOp, ast.Num)):
continue
if not isinstance(node, allowed):
return False
except SyntaxError:
return False
return True
print(check('6**8')) # False
print(check('-6+2')) # False
print(check('6*(2+3)')) # True
的值为6**8
,因为它由False
节点表示,第二种情况是因为ast.Pow
对应于-6
。