如何对字符串进行数学运算?
How to do math operations with string?
如果有字符串calculation = '1+1x8'
。如何将其转换为 calculation = 1+1*8
?我尝试做类似
的事情
for char in calculation:
if char == 'x':
calculation = calculation.replace('x', *)
# and
if char == '1':
calculation = calculation.replace('1', 1)
这显然行不通,因为您不能只用一个整数替换一个字符。整个字符串需要是一个整数,如果我这样做它也不起作用,因为我无法将 'x'
和 '+'
转换为整数
你可以这样写:
def parse_exp(s):
return eval(s.replace('x','*'))
并扩展您要使用的任何其他奇异符号。
要限制 eval 的风险,您还可以消除不良字符:
import string
good = string.digits + '()/*+-x'
def parse_exp(s):
s2 = ''.join([i for i in s if i in good])
return eval(s2.replace('x','*'))
编辑:额外的好处是内置的 eval
函数会处理括号和一般计算规则之类的事情:)
编辑 2:正如另一位用户指出的那样,eval
can be dangerous。因此,仅当您的代码仅在本地 运行
时才使用它
我们以一个更复杂的字符串为例:1+12x8
。以下是一个粗略的大纲;您需要为每个步骤提供实现。
首先,你将它标记化,将 1+12x8
变成 ['1', '+', '12', 'x', '8']
。对于此步骤,您需要编写分词器或词法分析器。这是您定义运算符和文字的步骤。
接下来,您将令牌流转换为解析树。也许您将树表示为 S-expression ['+', '1', ['x', '12', '8']]
或 [operator.add, 1, [operator.mul, 12, 8]]
。这一步需要编写一个解析器,这需要您定义诸如运算符优先级之类的东西。
最后,您编写了一个可以将解析树缩减为单个值的求值器。分两步执行此操作可能会产生
[operator.add, 1, [operator.mul, 12, 8]]
到 [operator.add, 1, 96]
[operator.add, 1, 96]
到 97
根据 chepner 的建议添加代码:
标记'1+12x8' -> ['1', '+', '12', 'x', '8']。
使用操作顺序 '/*+-' -> reduce 计算 1 + (12*8)
Return答案
import re
import operator
operators = {
'/': operator.truediv,
'x':operator.mul,
'+':operator.add,
'-':operator.sub,
}
def op(operators, data):
# apply operating to all occurrences
for p in operators:
while p in data:
x = data.index(p)
replacer = operators.get(p)(int(data[x-1]) , int(data[x+1]))
data[x-1] = replacer
del data[x:x+2]
return data[0]
def func(data):
# Tokenize
d = [i for i in re.split('(\d+)', data) if i ]
# Use order of operations
d = op(operators, d)
return d
s1 = "1+1x8"
s2 = '2-4/2+5'
s = func(s1) # 9
print(s)
t = func(s2) #-5
print(t)
如果有字符串calculation = '1+1x8'
。如何将其转换为 calculation = 1+1*8
?我尝试做类似
for char in calculation:
if char == 'x':
calculation = calculation.replace('x', *)
# and
if char == '1':
calculation = calculation.replace('1', 1)
这显然行不通,因为您不能只用一个整数替换一个字符。整个字符串需要是一个整数,如果我这样做它也不起作用,因为我无法将 'x'
和 '+'
转换为整数
你可以这样写:
def parse_exp(s):
return eval(s.replace('x','*'))
并扩展您要使用的任何其他奇异符号。
要限制 eval 的风险,您还可以消除不良字符:
import string
good = string.digits + '()/*+-x'
def parse_exp(s):
s2 = ''.join([i for i in s if i in good])
return eval(s2.replace('x','*'))
编辑:额外的好处是内置的 eval
函数会处理括号和一般计算规则之类的事情:)
编辑 2:正如另一位用户指出的那样,eval
can be dangerous。因此,仅当您的代码仅在本地 运行
我们以一个更复杂的字符串为例:1+12x8
。以下是一个粗略的大纲;您需要为每个步骤提供实现。
首先,你将它标记化,将 1+12x8
变成 ['1', '+', '12', 'x', '8']
。对于此步骤,您需要编写分词器或词法分析器。这是您定义运算符和文字的步骤。
接下来,您将令牌流转换为解析树。也许您将树表示为 S-expression ['+', '1', ['x', '12', '8']]
或 [operator.add, 1, [operator.mul, 12, 8]]
。这一步需要编写一个解析器,这需要您定义诸如运算符优先级之类的东西。
最后,您编写了一个可以将解析树缩减为单个值的求值器。分两步执行此操作可能会产生
[operator.add, 1, [operator.mul, 12, 8]]
到[operator.add, 1, 96]
[operator.add, 1, 96]
到97
根据 chepner 的建议添加代码:
标记'1+12x8' -> ['1', '+', '12', 'x', '8']。 使用操作顺序 '/*+-' -> reduce 计算 1 + (12*8) Return答案
import re
import operator
operators = {
'/': operator.truediv,
'x':operator.mul,
'+':operator.add,
'-':operator.sub,
}
def op(operators, data):
# apply operating to all occurrences
for p in operators:
while p in data:
x = data.index(p)
replacer = operators.get(p)(int(data[x-1]) , int(data[x+1]))
data[x-1] = replacer
del data[x:x+2]
return data[0]
def func(data):
# Tokenize
d = [i for i in re.split('(\d+)', data) if i ]
# Use order of operations
d = op(operators, d)
return d
s1 = "1+1x8"
s2 = '2-4/2+5'
s = func(s1) # 9
print(s)
t = func(s2) #-5
print(t)